https://acm.hdu.edu.cn/showproblem.php?pid=7064
问子串在母串中不重叠地出现最多多少次。
正解哈希,子串长度只有30就直接枚举母串中所有长度30以里的串哈希然后乱搞一通就行。
但是这题数据范围给的很离谱,给了其他做法可乘之机。如果我们**处理掉所有的重复的字符串**(不判重很容易卡)的话,不难发现数据拉满的最坏情况下平均一个子串长度才4,因此建立Trie高度不会很高(或者说,可能会有几条链很长但是整体很短),因此暴力跑Trie也能过。
(这题最后就剩1h不到了因此急了瞎98交了14发……虽然其中很大程度是在二分Trie树该开多大我一直怀疑它数据没改QAQ)
#include<map> #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e5+5; const int M=4e6+5; struct Trie{ map<int,int>a; vector<int>ed; }tr[M]; int cnt,n,ans[N],tans[N],where[N],len[N]; string s,bs; void insert(int id){ int m=len[id],now=0; for(int i=0;i<m;i++){ int c=s[i]-'a'; if(!tr[now].a[c])tr[now].a[c]=++cnt; now=tr[now].a[c]; } tr[now].ed.push_back(id); return; } int tot; map<string,int>mp; vector<int>in[N]; void init(){ for(int i=0;i<=cnt;i++){ tr[i].a.clear(); tr[i].ed.clear(); } for(int i=1;i<=tot;i++){ ans[i]=0; in[i].clear(); } mp.clear(); cnt=tot=0; } int main(){ int T; scanf("%d",&T); while(T--){ init(); cin>>bs>>n; for(int i=1;i<=n;i++){ cin>>s; if(!mp[s]){ mp[s]=++tot; len[tot]=s.length(); insert(mp[s]); where[tot]=-len[tot]; } in[mp[s]].push_back(i); } int m=bs.length(); for(int i=0;i<m;i++){ int now=0; for(int j=i;j<m;j++){ if(!tr[now].a.count(bs[j]-'a'))break; now=tr[now].a[bs[j]-'a']; for(int k=0;k<tr[now].ed.size();k++){ int id=tr[now].ed[k]; if(where[id]+len[id]<=i){ where[id]=i; ans[id]++; } } } } for(int i=1;i<=tot;i++){ for(int j=0;j<in[i].size();j++){ tans[in[i][j]]=ans[i]; } } for(int i=1;i<=n;i++)printf("%d\n",tans[i]); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++