• Remember The Word-Trie


    题目: 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
    ",cas++,ans[len]);
        }
        return  0;
    }
    
  • 相关阅读:
    httpclient 5.0 设置超时时间
    httpclient raw请求
    使用EasyUI-datagrid-export.js导出Excel,不导出隐藏列
    ExpressSet 虚拟适配器
    中断模式队列
    autohotkey 线程入门
    读rbtree
    树莓派串口
    MCP3421使用详解
    PMOS开关电路
  • 原文地址:https://www.cnblogs.com/lccurious/p/5079876.html
Copyright © 2020-2023  润新知