【Luogu P4127】[AHOI2009]同類分佈
阿新 • • 發佈:2020-07-19
A | All with Pairs |
首先:得感謝我的隊友,因為我之前在趕課設,完全沒有去補題,神鵰俠侶,我是其中的雕
題意:將n個字串輸入,然後求s[i]的字首和s[j]的字尾匹配的最大長度,平方,求和
思考:補這道題可謂是經歷了九九八十一難,顯示自己一直在懷疑自己題目意思是否看懂,結果發現自己的確沒有理解題意,然後多虧了群巨暮雨忽來的幫助,我理解了題目的意思,只有確認了,自己字串操作已經是傻逼了,只能重新把之前的字串的KMP,hash,trie和AC自動機全部重新看一遍,看前面三個一小時,AC自動機看了一上午都沒有整明白,真的是廢了(之前也沒有整明白)
整完之後AC自動機整了半天,自己的思路是將所有的字串進行建立trie圖,注意以為節點建立fail,然後不斷一個一個列舉最大長度,結論:還是不行 最後再劉小哥哥的思路之下開拓了,直接就是將所以的字串進行hash,然後不斷的進行存入map陣列中,之後統計每個字串的字首在map中出現的次數。
因為考慮到去重,需要將每個字串的next陣列給求出來,然後減去就可以了,程式碼如下(參考的,之後自己搞一搞AC自動機做法,群巨推薦),為了趕時間,臨時補一下:
#include <iostream> #include <cstring> #include <string> #include <cmath> #include <cstdio> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <vector> #include <set> #include <map> #include <iomanip> #define rep(i,a,b) for(int i = a; i <= b ; i ++ ) #define pre(i,a,b) for(int i = b ; i >= a ; i --) #define ll long long #define inf 0x3f3f3f3f #define ull unsigned long long #define ios ios::sync_with_stdio(false),cin.tie(0) using namespace std; typedef pair<int,int> PII ; const int N=2e6+10,mod=998244353,p=233; string s[N]; string T; ull Hash[N]; ull pp[N]; map<ull, ull> mmap; ull cnt[N]; int ne[N]; int slen, tlen; void getnext() { int j, k; j = 0; k = -1; ne[0] = -1; while(j < tlen) { if(k == -1 || T[j] == T[k]) ne[++j] = ++k; else k = ne[k]; } } bool kmp(char *s,char *p) { int m=strlen(s); int n=strlen(p); for(int i=0,j=-1; i<=m; i++) { while(j && s[i]!=p[j+1]) { j=ne[j]; } if(s[i]==p[j+1]) { j++; } if(j==n) //匹配成功 { return true; } } return false; } int main(int argc, char const *argv[]) { ios; int n; scanf("%d", &n); pp[0] = 1; for(int i = 1; i < N; i++) { pp[i] = 1ll * pp[i - 1] * p % mod; } for(int i = 1; i <= n; i++) { cin >> s[i]; int len = s[i].size(); ull base = 1; ull hs = 0; for(int j = len - 1; j >= 0; --j) { hs += base * s[i][j]; mmap[hs]++; base *= p; } } ull ans = 0; for(int i = 1; i <= n; i++) { T = s[i]; tlen = T.size(); ull hs = 0; for(int j = 0; j < tlen; j++) { cnt[j] = 0; hs = hs * p + s[i][j]; if(!mmap.count(hs)) continue; cnt[j] += mmap[hs]; } getnext(); for(int j = 1; j <= tlen; j++) { if(ne[j] == 0) continue; cnt[ne[j] - 1] -= cnt[j - 1]; } for(int j = 0; j < tlen; j++) { ans = (ans + 1ll * (j + 1) * (j + 1) % mod * cnt[j] % mod) % mod; } } cout << ans << endl; return 0; }
B | Boundary |
C | Cover the Tree |
D | Duration |
E | Exclusive OR |
F | Fake Maxpooling |
G | Greater and Greater |
H | Happy Triangle |
I | Interval |
J | Just Shuffle |
K | Keyboard Free |