HDU2296(AC 로봇 + DP)

7448 단어 AC 로봇DP

Ring


Problem Description


For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic string engraved on. The string’s length should not exceed N. The careful Steven knows Jane so deeply that he knows her favorite words, such as “love”, “forever”. Also, he knows the value of each word. The higher value a word has the more joy Jane will get when see it. The weight of a word is defined as its appeared times in the romantic string multiply by its value, while the weight of the romantic string is defined as the sum of all words’ weight. You should output the string making its weight maximal.

Input


The input consists of several test cases. The first line of input consists of an integer T, indicating the number of test cases. Each test case starts with a line consisting of two integers: N, M, indicating the string’s length and the number of Jane’s favorite words. Each of the following M lines consists of a favorite word Si. The last line of each test case consists of M integers, while the i-th number indicates the value of Si. Technical Specification
  • T ≤ 15
  • 0 < N ≤ 50, 0 < M ≤ 100.
  • The length of each word is less than 11 and bigger than 0.
  • 1 ≤ Hi ≤ 100.
  • All the words in the input are different.
  • All the words just consist of ‘a’ - ‘z’.

  • Output


    For each test case, output the string to engrave on a single line. If there’s more than one possible answer, first output the shortest one. If there are still multiple solutions, output the smallest in lexicographically order.
    The answer may be an empty string.

    Sample Input


    2 7 2 love ever 5 5 5 1 ab 5

    Sample Output


    lovever abab

    Hint


    Sample 1: weight(love) = 5, weight(ever) = 5, so weight(lovever) = 5 + 5 = 10 Sample 2: weight(ab) = 2 * 5 = 10, so weight(abab) = 10

    제목 대의:


    n 길이를 초과하지 않는 문자열을 구성하여
    ∑i=1mhi 문자열에 나타나는 횟수
    최대
    만약 여러 개의 열이 모두 충족된다면 길이가 가장 작고, 길이가 같은 것이 있다면 사전 순서가 가장 작아야 한다

    solution:


    여러 모드열이 있고 길이가 크지 않아 AC 자동기를 구축할 생각을 하기 쉽다.그리고 방법이 분명해졌다. 트리뷰에서 DP를 뛰는 것이다.
    f[i][j]는 길이가 i임을 나타내고 j호 노드의 최대 가치pre[i][j]는 f[i][j]의 가장 좋은 이동의 출처를 나타낸다.
    이동은 매우 간단해서 할 말이 없지만 문자열을 요구할 때는 이동할 때 주의해야 한다. 세부 사항이 좀 많다

    code:

    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
    int sl,best,T,Max,n,len,son[70000][26],w[70000],num,hz[70000],que[70000],head,tail,f[55][70000],val[70000];
    struct czy{
        int a,b,c;
    }pre[55][70000],id;
    char ch[150],ans[1000],now[1000];
    bool ok(int a,int b){
        id=pre[a][b];
        while(1){
            now[id.a]=id.c+'a';
            if(!id.a)
                break;
            id=pre[id.a][id.b];
        }
        for(int i=0;iif(ans[i]return false;
            else
            if(ans[i]>now[i])
                return true;
        return false;
    }
    bool check1(int a,int b,int c,char d){
        id=pre[a-1][b];
        while(1){
            ch[id.a]=id.c+'a';
            if(!id.a)
                break;
            id=pre[id.a][id.b];
        }
        ch[a-1]=d;
        id=pre[a][c];
        while(1){
            now[id.a]=id.c+'a';
            if(!id.a)
                break;
            id=pre[id.a][id.b];
        }
        for(int i=0;iif(now[i]return false;
    else
    if(now[i]>ch[i])
    return true;    
    return false;
    }
    int main(){
    scanf("%d",&T);
    while(T--){
    scanf("%d%d",&Max,&n);
    num=1;
    memset(son,0,sizeof(son));
    memset(hz,0,sizeof(hz));
    memset(f,0,sizeof(f));
    memset(w,0,sizeof(w));
    for(int i=1;i<=n;i++){
    scanf("%s",ch);
    len=strlen(ch);
    int x=1;
    for(int j=0;jif(son[x][ch[j]-'a'])
    x=son[x][ch[j]-'a'];
    else
    x=son[x][ch[j]-'a']=++num;
    w[x]=i;
    }
    for(int i=1;i<=n;i++)
    scanf("%d",&val[i]);
    head=1;
    tail=0;
    for(int i=0;i<26;i++)
    if(son[1][i]){
    hz[son[1][i]]=1;
    que[++tail]=son[1][i];
    }
    else
    son[1][i]=1;
    while(head<=tail){
    int u=que[head++];
    for(int i=0;i<26;i++)
    if(son[u][i]){
    hz[son[u][i]]=son[hz[u]][i];
    que[++tail]=son[u][i];
    }
    else
    son[u][i]=son[hz[u]][i];
    }
    for(int i=0;i<=Max;i++)
    for(int j=1;j<=num;j++){
    pre[i][j]=(czy){0,0,0};
    f[i][j]=-1;
    }
    f[0][1]=0;
    best=0;
    sl=0;
    for(int i=1;i<=Max;i++)
    for(int j=1;j<=num;j++)
    if(f[i-1][j]!=-1){
    for(int k=0;k<26;k++){
    int v=son[j][k];
    if((f[i][v]==-1)||(f[i][v]1][j]+val[w[v]])||(f[i][v]==f[i-1][j]+val[w[v]])&&check1(i,j,v,k+'a')){
    pre[i][v]=(czy){i-1,j,k};
    f[i][v]=f[i-1][j]+val[w[v]];
    }
    }
    }
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=Max;i++)
    for(int j=1;j<=num;j++){
    if(f[i][j]>best||f[i][j]==best&&i==sl&&ok(i,j)){
    best=f[i][j];
    sl=i;
    id=pre[i][j];
    while(1){
    now[id.a]=id.c+'a';
    if(!id.a)
    break;
    id=pre[id.a][id.b];
    }
    for(int k=0;kfor(int i=0;iputchar(ans[i]);
    puts("");
    }
    return 0;
    }

    좋은 웹페이지 즐겨찾기