위키오-엘리베이터-보급 일등-구분 dp-1040: 단어 개수 통계

3666 단어 dpWIKIOI사다리

제목 설명Description


길이가 200을 넘지 않는 소문자 영문 자모로 구성된 자모열을 제시한다.이 알파벳을 k부로 나누기 (1

설명 입력 Input Description


첫 번째 행위의 정수(0

출력 설명 Output Description


줄마다 정수가 하나씩 있고 각 그룹의 테스트 데이터에 대응하는 상응하는 결과이다.

샘플 Sample Input 입력


1 1 3 thisisabookyouareaoh 4 is a ok sab

샘플 출력 Sample Output


7

데이터 범위 및 프롬프트 Data Size & Hint


this/isabookyoua/reaoh
유형:dp 난이도:2
제목: 문자열과 s개의 단어가 있는 사전을 보여 줍니다. 이 문자열을 k부로 나누어 단어의 총수를 최대로 나누는 방법을 구합니다.문자열에서 두 단어는 같은 위치에서 열 수 없지만 같은 위치에서 끝낼 수 있습니다.즉,this와th는 하나만 계산할 수 있지만,this와is는 두 개로 계산한다.
분석: 우선 문자열 중의 단어의 개수와 위치를 통계해야 한다. 나의 방법은len[i]으로 i에서 시작한 단어의 최소 길이를 기록하는 것이다. (두 단어는 한 위치에서 시작할 수 없기 때문에 한 위치에서 시작한 단어는 하나만 취할 수 있다. 분명히 취한 단어는 짧을수록 구분의 영향을 받지 않고 더 많은 단어를 얻기 쉽다.)
그리고 dp 구분으로 해결하고 dp[pos][k]로 문자열을pos 위치에서 끝까지의 문자열을 k분으로 나누어 얻을 수 있는 최대 단어수로 나눈다.
추이 방정식: dp[pos][k] = mmax(cnt+dp[i+1][k-1]), 그 중에서 i는 이번 구분의 위치이고, cnt는 [pos, i] 이 단락의 문자열에 포함된 단어수, dp[0][k]
코드는 다음과 같습니다.
#include<iostream>
#include<cstring>
#include<string>
using namespace std;

int len[210],dp[210][210];
string sen;

int mmin(int a,int b)
{
    if(a<0) return b;
    if(b<0) return a;
    return (a<b)?a:b;
}

int mmax(int a,int b)
{
    return (a>b)?a:b;
}

int fun(int pos,int k)
{
    if(pos<0 || k<=0) return 0;
    if(dp[pos][k]>0) return dp[pos][k];
    
    int endcnt[210],cnt = 0;
    memset(endcnt,0,sizeof(endcnt));
    
    for(int i=pos; i<=sen.length()-k; i++)
    {
        if(len[i]>0)
            endcnt[i+len[i]-1]++;
        cnt += endcnt[i];
        dp[pos][k] = mmax(dp[pos][k],cnt+fun(i+1,k-1));
    }
    return dp[pos][k];
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(len,-1,sizeof(len));
        memset(dp,0,sizeof(dp));
        
        int p,k;
        cin>>p>>k;
        string tmp;
        while(p--)
        {
            cin>>tmp;
            sen += tmp;
        }
        
        int s;
        cin>>s;
        while(s--)
        {
            string word;
            cin>>word;
            for(int i=0; i<=sen.length()-word.length(); i++)
            {
                string sub(sen.substr(i,word.length()));
                if(word == sub)
                    len[i] = mmin(len[i],word.length());
            }
        }
        cout<<fun(0,k)<<endl;
    }
}

 

좋은 웹페이지 즐겨찾기