UVALive - 5913 Dictionary Size

来源:互联网 发布:中国生物文献数据库 编辑:程序博客网 时间:2024/06/05 07:04

题意:求有前后缀组成的不同的字符串

思路:先用Trie树来统计前后缀不同的字符串,然后就是去重

例如:前后缀分别是x1x1x1x1a,ax2x2x2x2x2的话,那么可能重复的字符串

x1x1x1x1ax2x2x2x2x2,统计前后缀分别以a结尾的个数,然后减去

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 500010;const int M = 26;char s[10010][45];int num1[26],num2[26],C[26],id[MAXN],sz;int ch[MAXN][M];void init(){    sz = 1;    memset(ch[0],0,sizeof(ch[0]));    for (int i = 0; i < M; i++)        id[i+'a'] = i;}void insert(char *s,int num[],int &cnt){    int u = 0,first = 1;    int len = strlen(s);    for (int i = 0; i < len; i++){        int c = id[s[i]];        if (!ch[u][c]){            memset(ch[sz],0,sizeof(ch[sz]));            cnt++;            if (!first)                num[c]++;            ch[u][c] = sz++;        }        first = 0;        u = ch[u][c];    }}int main(){    int n;    while (scanf("%d",&n) != EOF){        memset(num1,0,sizeof(num1));        memset(num2,0,sizeof(num2));        memset(C,0,sizeof(C));        init();        int cnt1 = 0,cnt2 = 0;        for (int i = 0; i < n; i++){            scanf("%s",s[i]);            insert(s[i],num1,cnt1);        }        init();        for (int i = 0; i < n; i++){           int len = strlen(s[i]);           if (len == 1)               C[s[i][0]-'a'] = 1;           std::reverse(s[i],s[i]+len);           insert(s[i],num2,cnt2);        }        long long ans = (long long)cnt1*cnt2;        for (int i = 0; i < 26; i++){            if (C[i])                ans++;            ans -= (long long)num1[i] * num2[i];        }        printf("%lld\n",ans);    }    return 0;}




1 0
原创粉丝点击