2020牛客暑期多校訓練營 第二場 A All with Pairs 字串hash KMP
阿新 • • 發佈:2020-07-14
LINK:All with Pairs
那天下午打這個東西的時候狀態極差 推這個東西都推了1個多小時 (比賽是中午考試的我很困 沒睡覺直接開肝果然不爽
一開始看錯匹配的位置了 以為是\(1-l\)和\(r-(r-l+1)\)進行匹配。
我想這不是隨便寫個trie樹???碼完發現過不去樣例 我真的是眼瞎
後來看清了。
大致思路如下 可以直接暴力列舉\(n^2\)個點對 找到最大的匹配位置這個也可以暴力 由於串長總和是M。
這一部分複雜度也不過是\(n^2+M\)的。
過不了 就可以思考能不能從大到小列舉匹配長度 看有多少對符合。
發現這樣也非常難做。
不過可以對單個串列舉匹配長度 然後看有多少個串可以進行匹配。
這樣容易想到字串hash 來進行快速的匹配 開C++11 直接unodered_map...
然後可以發現這樣做 會帶來重複 仔細觀察對於同一個串的重複位置 可以發現這是一個KMP的nex陣列的問題。
然後每次統計到一個位置就把自己的nex陣列的那個位置給減掉即可。
code
//#include<bits\stdc++.h> #include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<cctype> #include<cstdlib> #include<queue> #include<deque> #include<stack> #include<vector> #include<algorithm> #include<utility> #include<bitset> #include<set> #include<map> #define ll long long #define db double #define INF 1000000000000000ll #define ldb long double #define pb push_back #define put_(x) printf("%d ",x); #define get(x) x=read() #define gt(x) scanf("%d",&x) #define gi(x) scanf("%lf",&x) #define put(x) printf("%d\n",x) #define putl(x) printf("%lld\n",x) #define gc(a) scanf("%s",a+1) #define rep(p,n,i) for(RE int i=p;i<=n;++i) #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]]) #define fep(n,p,i) for(RE int i=n;i>=p;--i) #define vep(p,n,i) for(RE int i=p;i<n;++i) #define pii pair<int,int> #define mk make_pair #define RE register #define P 13331 #define gf(x) scanf("%lf",&x) #define pf(x) ((x)*(x)) #define uint unsigned long long #define ui unsigned #define EPS 1e-4 #define sq sqrt #define S second #define F first #define len(x) t[x].len #define en(x) t[x].en #define mod 998244353 #define M 1000000007 using namespace std; const int MAXN=100010,maxn=1000010; int n,cnt; string a[MAXN];ll c[maxn]; map<ll,int>H[maxn]; ll p[maxn]; char b[maxn]; int nex[maxn];ll w[maxn]; inline void kmp(int n) { int j=0; rep(2,n,i) { while(j&&b[j+1]!=b[i])j=nex[j]; if(b[j+1]==b[i])++j; nex[i]=j; } } int main() { //freopen("1.in","r",stdin); ios::sync_with_stdio(false); cin>>n;int mx=0; rep(1,n,i) { cin>>a[i]; mx=max(mx,(int)a[i].size()); ll ha=0; vep(0,a[i].size(),j) { ha=(ha*P%M+(a[i][j]-'a'+1))%M; ++H[j+1][ha]; } } p[0]=1; rep(1,mx,i)p[i]=(ll)p[i-1]*P%M; rep(1,n,i) { ll ha=0; reverse(a[i].begin(),a[i].end()); int cnt=0; vep(0,a[i].size(),j)b[++cnt]=a[i][j],w[cnt]=0; kmp(cnt);cnt=0; vep(0,a[i].size(),j) { ++cnt; ha=(ha+(a[i][j]-'a'+1)*(ll)p[cnt-1])%M; if(H[cnt].find(ha)!=H[cnt].end()) { ll cc=H[cnt][ha]; c[cnt]+=cc; w[nex[cnt]]+=cc; } } rep(1,cnt,j)c[j]-=w[j]; } ll ans=0; fep(mx,1,i)ans=(ans+(ll)i*i*c[i])%mod; cout<<ans<<endl;return 0; }