设d[i]表示从下标i的字符开始的字符串的分解方法数,显然有倒序的递推公式。
需要求每个位置开始是否能组成模式串的前缀,才可以建立正确的递推。
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue> 8 #include <set> 9 #include <map> 10 #include <list> 11 #include <vector> 12 #include <stack> 13 #define mp make_pair 14 #define MIN(a,b) (a>b?b:a) 15 #define rank rankk 16 //#define MAX(a,b) (a>b?a:b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int MAX=3e5+5; 20 const int INF=1e9+5; 21 const int B=1024;//桶的大小 22 const double M=4e18; 23 const int MAX_NODE=MAX; 24 const int sigma_size=30; 25 using namespace std; 26 //const int MOD=1e9+7; 27 const int MOD=20071027; 28 typedef pair<int,int> pii; 29 const double eps=0.000000001; 30 31 struct Trie 32 { 33 int ch[MAX_NODE][sigma_size];//点数、“字母”数 34 int val[MAX_NODE]; 35 int num;//结点总数 36 Trie(){num=1;memset(ch[0],0,sizeof(ch[0]));}//初始时仅有根节点 37 void clear() { num = 1; memset(ch[0], 0, sizeof(ch[0])); } 38 int idx(char c)//返回对应字符的编号 39 { 40 return c-‘a‘; 41 } 42 /* 43 插入字符串s,附加信息为v。注意v必须非0,因为0代表:本结点不是单词结点 44 */ 45 void insert(const char *s,int v) 46 { 47 int u=0,len=strlen(s); 48 for(int i=0;i<len;i++) 49 { 50 int c=idx(s[i]); 51 if(!ch[u][c])//结点不存在 52 { 53 memset(ch[num],0,sizeof(ch[num])); 54 val[num]=0;//中间节点的附加信息为0 55 ch[u][c]=num++;//新建结点 56 } 57 u=ch[u][c];//往下走 58 } 59 val[u]=v;//字符串的最后一个字符的附加信息为v 60 } 61 /* 62 查询字符串的“附加信息” 63 查询过程中间中断返回0 64 */ 65 int check(char *s) 66 { 67 int u=0,len=strlen(s); 68 for(int i=0;i<len;i++) 69 { 70 int c=idx(s[i]); 71 if(!ch[u][c]) 72 return 0; 73 u=ch[u][c]; 74 } 75 return val[u]; 76 } 77 /* 78 找字符串s的长度不超过len的前缀 79 */ 80 void find_prefixes(const char *s,int len,vector <int> &ans) 81 { 82 int u=0; 83 for(int i=0;i<len;i++) 84 { 85 if(s[i]==‘\0‘) 86 break; 87 int c=idx(s[i]); 88 if(!ch[u][c]) 89 break; 90 u=ch[u][c]; 91 if(val[u]!=0)//过程中所有找到的全都push进去 92 ans.push_back(val[u]); 93 } 94 } 95 }; 96 char a[MAX]; 97 int s,d[MAX],len,siz[MAX],cnt; 98 Trie dic; 99 char tem[MAX]; 100 vector <int> an; 101 int main() 102 { 103 while(~scanf("%s",a)) 104 { 105 dic.clear(); 106 an.clear(); 107 scanf("%d",&s); 108 for(int i=1;i<=s;i++) 109 { 110 scanf("%s",tem); 111 siz[i]=strlen(tem); 112 dic.insert(tem,i); 113 } 114 memset(d,0,sizeof(d)); 115 len=strlen(a); 116 d[len]=1; 117 for(int i=len-1;i>=0;i--) 118 { 119 an.clear(); 120 dic.find_prefixes(a+i,len-i,an); 121 for(int j=0;j<an.size();j++) 122 { 123 d[i]=(d[i]+d[i+siz[an[j]]])%MOD; 124 } 125 } 126 printf("Case %d: %d\n",++cnt,d[0]); 127 } 128 }
时间: 2024-10-17 11:55:45