首页 > 代码库 > UVA 1401Remember the WordDp

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;}