您的位置:首页 > 其它

Remember The Word-Trie

2015-07-23 14:29 190 查看
题目: UVaLive 3942

#include<cstdio>
#include<cstring>

using namespace std;

const int MAX = 4010 * 100;         //题目中说过每个样例S<4000 单个长度<100
const int MOD = 20071027;
int sz = 1;                         //用来记录每个字母的顺序
char str;
int ch[MAX][26];
int flag[MAX];                      //用来标识每个单词是否已经结束
int ans[300010];

void clearw(){
sz = 1;
memset(ch[0],0,sizeof(ch[0]));
memset(flag,0,sizeof(flag));
}
//创建一个新的字母节点
int creatw(int u){
memset(ch[sz],0,sizeof(ch[sz]));
flag[sz] = u;
return  sz++;
}
/*插入函数:用来插入新的单词,如果在这一层已经存在这个字母了,继续往下摸,否则就
*创建一个新的节点,在单词的最后设立一个结束的哨兵。这样建成一棵字典树。
*/
int insertw(char *s){
int u = 0;
int len = strlen(s);
for(int i = 0;i < len;i++){
int v = s[i] - 'a';
if(!ch[u][v])
ch[u][v] = creatw(0);
u = ch[u][v];
}
flag[u] = 1;
}
/*查找函数:根据给定的深度和字符串开始搜索。依然是用s[i]-'a'来判断那个对应的位置
*是不是符合条件,如果符合则这一层的就加上,因为所有这一层是不是有符合长度的字符串
*都已经被压缩在flag中去了,所以只要flag是真,那就是可以相加,然后逐层相加,取模
*即可
*/
void findw(int con,char *s){
int u = 0;
int deep = 0;
for(; *s; s++){
int v = *s - 'a';
if(ch[u][v]){
deep ++;
u = ch[u][v];
ans[con+deep] = (ans[con]*flag[u] + ans[con+deep])%MOD;
}//因为要取MOD所以写成如此,不然也可以写成+=;
else
break;

}
}

int main(){
char str[300010];
int cas = 1;
while(~scanf("%s",str)){
clearw();
memset(ans,0,sizeof(ans));
int len = strlen(str);
ans[0] = 1;//这里非常重要,第一个一定是符合的
int num;
scanf("%d",&num);
char strt[110];
while(num--){
scanf("%s",strt);
insertw(strt);
}
for(int i = 1;i <= len;i++){
findw(i-1,str+i-1);//因为是从最完整一个单词开始拆。
}

printf("Case %d: %d\n",cas++,ans[len]);
}
return  0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: