UVA 1401Remember the WordDp

 此题开始 用记忆化搜索搞,我果然白痴,字符串30w 的长度 ,爆栈是肯定的。

dp转移的方程: str[i->j]  如果出现  dp[i] += dp[j+1] 

然后用字典树查询 str[i->j]是否出现过。

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <climits>

#include <string>

#include <iostream>

#include <map>

#include <cstdlib>

#include <list>

#include <set>

#include <queue>

#include <stack>

using namespace std;



char str[333333];

struct Node

{

    int gaoguo ; struct Node* next[30];

}node[2111111];

const int mod= 20071027;

int len;

Node* newnode()

{

    memset(&node[len],0,sizeof(node[len]));

    return &node[len++];

}

Node *rt;

void Insert(string s,Node*root)

{

    int len2=s.size();

    for(int i= 0;i< len2;i++){

        int cc=s[i]-'a';

        if(!root->next[cc]){

            root->next[cc]=newnode();

        }

        root=root->next[cc];

    }

    root->gaoguo=1;

}



int ask(string s,Node *root)

{

    int len2=s.size();

    for(int i=0;i<len2;i++){

        int cc=s[i]-'a';

        if(root->next[cc])

            root=root->next[cc];

        else return -1;

    }

    return root->gaoguo;

}

int len1;

int dp[333333];

char str1[333333];

int main()

{

    int n;

    int Icase= 0;

    while(scanf("%s",str)!=EOF){

        memset(dp,0,sizeof(dp));

        len1=strlen(str);

        scanf("%d",&n);

        len=0; rt = newnode();

        for(int i=0;i<n;i++){

            scanf("%s",str1); Insert(str1,rt);

        }

        printf("Case %d: ",++Icase);

        dp[len1]=1;

        for(int i=len1-1;i>=0;i--){

            string s="";

            for(int j=i;j<len1;j++){

                s+=str[j];

              //  cout<<s<<" "<<ask(s,rt)<<endl;

                int cc=ask(s,rt);if(cc==-1) break;

                if(cc==1) dp[i]+=dp[j+1],dp[i]%=mod;

            }

        }

        cout<<dp[0]%mod<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(word)