题意:求有前后缀组成的不同的字符串
思路:先用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; }