mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
402 lines
13 KiB
Plaintext
402 lines
13 KiB
Plaintext
|
//hash_fun.h
|
|||
|
inline size_t __stl_hash_string(const char *s) {
|
|||
|
size_t h = 0;
|
|||
|
for (; *s; ++s) { h = 5 * h + *s; }
|
|||
|
return h;
|
|||
|
}
|
|||
|
//for hash_map<string, XXX>
|
|||
|
struct str_hash {
|
|||
|
size_t operator()(const string &str)const {
|
|||
|
return __stl_hash_string(str.c_str());
|
|||
|
}
|
|||
|
};
|
|||
|
//BKDR Hash Function
|
|||
|
inline size_t BKDRHash(const char *str) {
|
|||
|
size_t h = 0, seed = 131; //31 131 1313 13131 131313 etc..
|
|||
|
while (*str) { h = h * seed + (*str++); }
|
|||
|
return h & 0x7FFFFFFF;
|
|||
|
}
|
|||
|
//<2F>ַ<EFBFBD><D6B7><EFBFBD>hash
|
|||
|
const int N = 20005, P = 31, D = 1000173169;
|
|||
|
int n, pp[N] = {1}, hs[N]; char s[N];
|
|||
|
int get(int l, int r) { return ((hs[r] - (ll)hs[l - 1] * pp[r - l + 1]) % D + D) % D; }
|
|||
|
int main() {
|
|||
|
scanf("%d%s", &n, s + 1);
|
|||
|
for (int i = 1; i <= n; i++) { pp[i] = pp[i - 1] * P % D; }
|
|||
|
for (int i = 1; i <= n; i++) { hs[i] = ((ll)hs[i - 1] * P + s[i]) % D; }
|
|||
|
}
|
|||
|
//<2F><>дhash_map
|
|||
|
const int P = 13131;
|
|||
|
char key[N][M];
|
|||
|
typedef struct Node { int id, val; } etype;
|
|||
|
template<size_t(*Hash)(const char *)> struct hashmap {
|
|||
|
vector<etype> hs[P];
|
|||
|
void init() { for (int i = 0; i < P; i++) { hs[i].clear(); } }
|
|||
|
void insert(int id, int val) {
|
|||
|
int h = Hash(key[id]) % P; hs[h].push_back((etype) {id, val});
|
|||
|
}
|
|||
|
bool erase(char *buf) {
|
|||
|
int h = Hash(buf) % P;
|
|||
|
for (size_t i = 0; i < n; i++) { if (!strcmp(buf, key[hs[h][i].id])) { hs[h].erase(hs[h].begin() + i); return true; } }
|
|||
|
return false;
|
|||
|
}
|
|||
|
int query(char *buf) {
|
|||
|
int h = Hash(buf) % P;
|
|||
|
for (size_t i = 0; i < n; i++) { if (!strcmp(buf, key[hs[h][i].id])) { return hs[h][i].val; } }
|
|||
|
return false;
|
|||
|
}
|
|||
|
};
|
|||
|
hashmap<BKDRHash> mp;
|
|||
|
//Manacher <20><EFBFBD><EEB3A4><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
|
|||
|
//<2F><EFBFBD><EEB3A4><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD>Ӧԭ<D3A6><D4AD>T<EFBFBD>е<EFBFBD>λ<EFBFBD><CEBB>: l = (i - R[i]) / 2; r = (i + R[i]) / 2 - 2;
|
|||
|
char s[N], tmp[N << 1];
|
|||
|
int dp[N << 1];
|
|||
|
void Manacher(char *s, int len) {
|
|||
|
int l = 0, mx = 0, id = 0; tmp[l++] = '$'; tmp[l++] = '#';
|
|||
|
for (int i = 0; i < len; i++) { tmp[l++] = s[i]; tmp[l++] = '#'; }
|
|||
|
tmp[l] = 0;
|
|||
|
for (int i = 0; i < l; i++) {
|
|||
|
dp[i] = mx > i ? min(dp[(id << 1) - i], mx - i) : 1;
|
|||
|
while (tmp[i + dp[i]] == tmp[i - dp[i]]) { dp[i]++; }
|
|||
|
if (i + dp[i] > mx) { mx = i + dp[i]; id = i; }
|
|||
|
}
|
|||
|
}
|
|||
|
int main() {
|
|||
|
while (~scanf("%s", s)) {
|
|||
|
int len = strlen(s), mlen = (len << 1) + 2, mxlen = 0, mxpos = 0;
|
|||
|
Manacher(s, len);
|
|||
|
for (int i = 0; i < mlen; i++) {
|
|||
|
if (mxlen < dp[i]) { mxlen = dp[i]; mxpos = i; }
|
|||
|
}
|
|||
|
printf("%d\n", mxlen - 1); //s.substr((mxpos - mxlen) >> 1, mxlen - 1);
|
|||
|
}
|
|||
|
}
|
|||
|
//<2F>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>ʾ
|
|||
|
int minString(char *s) {
|
|||
|
int m = strlen(s), i, j, k;
|
|||
|
char ss[m << 1]; strcpy(ss, s); strcpy(ss + m, s);
|
|||
|
for (i = k = 0, j = 1; k < m && i < m && j < m;) {
|
|||
|
for (k = 0; k < m && ss[i + k] == ss[j + k]; k++);
|
|||
|
if (k < m) {
|
|||
|
if (ss[i + k] > ss[j + k]) { i += k + 1; } //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<
|
|||
|
else { j += k + 1; }
|
|||
|
if (i == j) { j++; }
|
|||
|
}
|
|||
|
}
|
|||
|
return min(i, j);
|
|||
|
}
|
|||
|
//strstr <20><>str1<72>в<EFBFBD><D0B2><EFBFBD>str2<72>ĵ<EFBFBD>һ<EFBFBD>γ<EFBFBD><CEB3><EFBFBD> <20><><EFBFBD><EFBFBD>NULL
|
|||
|
char *strstr(const char *str1, const char *str2);
|
|||
|
//KMP O(M + N)
|
|||
|
//nxt[]<5D>ĺ<EFBFBD><C4BA>壺x[i-nxt[i]...i-1]=x[0...nxt[i]-1]
|
|||
|
//nxt[i]Ϊ<><CEAA><EFBFBD><EFBFBD>x[i-z...i-1]=x[0...z-1]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>zֵ(<28><><EFBFBD><EFBFBD>x<EFBFBD><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>)
|
|||
|
char x[N], y[N];
|
|||
|
int nxt[N];
|
|||
|
void getnxt(char *x, int m, int nxt[]) {
|
|||
|
int i = 0, j = -1; nxt[0] = -1;
|
|||
|
while (i < m) {
|
|||
|
while (j != -1 && x[i] != x[j]) { j = nxt[j]; }
|
|||
|
nxt[++i] = ++j;
|
|||
|
}
|
|||
|
}
|
|||
|
//<2F>Ľ<EFBFBD><C4BD><EFBFBD>
|
|||
|
void getnxt(char *x, int m, int nxt[]) {
|
|||
|
int i = 0, j = -1; nxt[0] = -1;
|
|||
|
while (i < m) {
|
|||
|
while (j != -1 && x[i] != x[j]) { j = nxt[j]; }
|
|||
|
if (x[++i] == x[++j]) { nxt[i] = nxt[j]; }
|
|||
|
else { nxt[i] = j; }
|
|||
|
}
|
|||
|
}
|
|||
|
//<2F><><EFBFBD><EFBFBD>x<EFBFBD><78>y<EFBFBD>г<EFBFBD><D0B3>ֵĴ<D6B5><C4B4><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>
|
|||
|
//x<><78>ģʽ<C4A3><CABD>, y<><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int KMPCount(char *x, int m, char *y, int n, int nxt[]/*, int &longest, int &lp*/) {
|
|||
|
int i = 0, j = 0, ans = 0; //longest = 0; lp = 0;
|
|||
|
while (i < n) {
|
|||
|
while (j != -1 && y[i] != x[j]) { j = nxt[j]; }
|
|||
|
i++; j++;
|
|||
|
//if (j > longest) { longest = j; lp = i - j; }
|
|||
|
if (j >= m) { j = nxt[j]; ans++; }
|
|||
|
}
|
|||
|
return ans;
|
|||
|
}
|
|||
|
//<2F><>չKMP
|
|||
|
//nxt[i]:x[i...m-1]<5D><>x[0...m-1]<5D><><EFBFBD><EFBFBD><EEB3A4><EFBFBD><EFBFBD>ǰ
|
|||
|
//ext[i]:y[i...n-1]<5D><>x[0...m-1]<5D><><EFBFBD><EFBFBD><EEB3A4><EFBFBD><EFBFBD>ǰ
|
|||
|
int nxt[N], ext[N];
|
|||
|
void getnxt(char *x, int m, int nxt[]) {
|
|||
|
int i = 2, j = 0, k = 1;
|
|||
|
while (j + 1 < m && x[j] == x[j + 1]) { j++; }
|
|||
|
nxt[0] = m; nxt[1] = j;
|
|||
|
for (; i < m; i++) {
|
|||
|
int p = nxt[k] + k - 1, l = nxt[i - k];
|
|||
|
if (i + l < p + 1) { nxt[i] = l; }
|
|||
|
else {
|
|||
|
j = max(0, p - i + 1);
|
|||
|
while (i + j < m && x[i + j] == x[j]) { j++; }
|
|||
|
nxt[i] = j; k = i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void getext(char *x, int m, char *y, int n, int nxt[], int ext[]) {
|
|||
|
getnxt(x, m);
|
|||
|
int i = 1, j = 0, k = 0;
|
|||
|
while (j < n && j < m && x[j] == y[j]) { j++; }
|
|||
|
ext[0] = j;
|
|||
|
for (; i < n; i++) {
|
|||
|
int p = ext[k] + k - 1, l = nxt[i - k];
|
|||
|
if (i + l < p + 1) { ext[i] = l; }
|
|||
|
else {
|
|||
|
j = max(0, p - i + 1);
|
|||
|
while (i + j < n && j < m && y[i + j] == x[j]) { j++; }
|
|||
|
ext[i] = j; k = i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//Sunday
|
|||
|
int Sunday(char *x, int m, char *y, int n) {
|
|||
|
int nxt[26] = {0};
|
|||
|
for (int j = 0; j < 26; j++) { nxt[j] = m + 1; }
|
|||
|
for (int j = 0; j < m; j++) { nxt[x[j] - 'a'] = m - j; }
|
|||
|
for (int pos = 0, i, j; pos <= n - m;) {
|
|||
|
for (i = pos, j = 0; j < m; i++, j++) {
|
|||
|
if (y[i] != x[j]) { pos += nxt[y[pos + m] - 'a']; break; }
|
|||
|
}
|
|||
|
if (j == m) { return pos; }
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
//Rabin-Karp
|
|||
|
#define UNSIGNED(x) ((unsigned char)x)
|
|||
|
const int d = 257;
|
|||
|
int hashMatch(char *s, int m, char *p, int n) {
|
|||
|
if (m > n || m == 0 || n == 0) { return -1; }
|
|||
|
//svΪs<CEAA>Ӵ<EFBFBD><D3B4><EFBFBD>hash<73><68><EFBFBD><EFBFBD>, pvΪp<CEAA><70>hash<73><68><EFBFBD><EFBFBD>, baseΪd<CEAA><64>m-1<>η<EFBFBD>
|
|||
|
unsigned sv = UNSIGNED(s[0]), pv = UNSIGNED(p[0]), base = 1;
|
|||
|
int i, j;
|
|||
|
//<2F><>ʼ<EFBFBD><CABC>sv, pv, base
|
|||
|
for (i = 1; i < m; i++) {
|
|||
|
pv = pv * d + UNSIGNED(p[i]);
|
|||
|
sv = sv * d + UNSIGNED(s[i]);
|
|||
|
base *= d;
|
|||
|
}
|
|||
|
i = m - 1;
|
|||
|
do {
|
|||
|
if (!(sv ^ pv)) {
|
|||
|
for (j = 0; j < m && s[i - m + 1 + j] == p[j]; j++);
|
|||
|
if (j == m) { return i - m + 1; }
|
|||
|
}
|
|||
|
if (++i >= n) { break; }
|
|||
|
//O(1)ʱ<><CAB1><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD>sv, sv + UNSIGNED(s[i - m]) * (~base + 1)<29>ȼ<EFBFBD><C8BC><EFBFBD>sv - UNSIGNED(s[i - m]) * base
|
|||
|
sv = (sv + UNSIGNED(s[i - m]) * (~base + 1)) * d + UNSIGNED(s[i]);
|
|||
|
} while (i < n);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
//Trie
|
|||
|
//<2F><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
|
|||
|
struct Trie {
|
|||
|
int nxt[N * 20][26], val[N * 20], root, tot;
|
|||
|
void init() { memset(nxt, 0, sizeof(nxt)); memset(val, 0, sizeof(val)); root = tot = 1; }
|
|||
|
void insert(char *buf, int id) {
|
|||
|
int len = strlen(buf), now = root;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
if (!nxt[now][c = buf[i] - 'a']) { nxt[now][c] = ++tot; }
|
|||
|
now = nxt[now][c];
|
|||
|
}
|
|||
|
val[now] = id;
|
|||
|
}
|
|||
|
int query(char *buf) {
|
|||
|
int len = strlen(buf), now = root;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
if (!nxt[now][c = buf[i] - 'a']) { return -1; }
|
|||
|
now = nxt[now][c];
|
|||
|
}
|
|||
|
return val[now];
|
|||
|
}
|
|||
|
} tr;
|
|||
|
//ָ<><D6B8>ʵ<EFBFBD><CAB5>
|
|||
|
struct Node { Node *nxt[26]; int val; };
|
|||
|
struct Trie {
|
|||
|
Node *root;
|
|||
|
void init() { erase(root); root = new Node(); }
|
|||
|
void insert(char *buf, int id) {
|
|||
|
int len = strlen(buf); Node *now = root;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
if (!now->nxt[c = buf[i] - 'a']) { now->nxt[c] = new Node(); }
|
|||
|
now = now->nxt[c];
|
|||
|
}
|
|||
|
now->val = id;
|
|||
|
}
|
|||
|
void erase(Node *p) {
|
|||
|
if (p) { for (int i = 0; i < 26; i++) { erase(p->nxt[i]); } delete p; }
|
|||
|
}
|
|||
|
int query(char *buf) {
|
|||
|
int len = strlen(buf); Node *now = root;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
if (!now->nxt[c = buf[i] - 'a']) { return -1; }
|
|||
|
now = now->nxt[c];
|
|||
|
}
|
|||
|
return now->val;
|
|||
|
}
|
|||
|
} tr;
|
|||
|
//AC<41>Զ<EFBFBD><D4B6><EFBFBD>
|
|||
|
struct AC {
|
|||
|
int nxt[N * 20][26], fail[N * 20], val[N * 20], root, tot;
|
|||
|
void init() { memset(nxt, 0, sizeof(nxt)); memset(val, 0, sizeof(val)); root = tot = 1; }
|
|||
|
void insert(char *buf, int id) {
|
|||
|
int len = strlen(buf), now = root;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
if (!nxt[now][c = buf[i] - 'a']) { nxt[now][c] = ++tot; }
|
|||
|
now = nxt[now][c];
|
|||
|
}
|
|||
|
val[now] = id;
|
|||
|
}
|
|||
|
void build() {
|
|||
|
queue<int> que; fail[root] = root;
|
|||
|
for (int i = 0; i < 26; i++) {
|
|||
|
if (!nxt[root][i]) { nxt[root][i] = root; }
|
|||
|
else { fail[nxt[root][i]] = root; que.push(nxt[root][i]); }
|
|||
|
}
|
|||
|
while (!que.empty()) {
|
|||
|
int now = que.front(); que.pop();
|
|||
|
for (int i = 0; i < 26; i++) {
|
|||
|
if (!nxt[now][i]) { nxt[now][i] = nxt[fail[now]][i]; }
|
|||
|
else { fail[nxt[now][i]] = nxt[fail[now]][i]; que.push(nxt[now][i]); }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
int query(char *buf) {
|
|||
|
int len = strlen(buf), now = root, res = 0;
|
|||
|
for (int i = 0, c; i < len; i++) {
|
|||
|
for (int tmp = now = nxt[now][c = buf[i] - 'a']; tmp != root; tmp = fail[tmp]) {
|
|||
|
res += val[tmp]; //val[tmp] = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
return res;
|
|||
|
}
|
|||
|
} ac;
|
|||
|
//<2F><><EFBFBD><D7BA><EFBFBD><EFBFBD>
|
|||
|
//n<><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
//m<><6D><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>С
|
|||
|
//s[0..n - 1]<5D><><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
|||
|
//sa[1..n]<5D><><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD> i С<><D0A1><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD>
|
|||
|
//rnk[0..n - 1]<5D><><EFBFBD><EFBFBD> i <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
//height[i]<5D><>lcp(sa[i], sa[i - 1])
|
|||
|
int rnk[N], sa[N], height[N], tmp[N], cnt[N];
|
|||
|
void SA(char *s, int n, int m) {
|
|||
|
int i, j, k; n++;
|
|||
|
memset(rnk, 0, sizeof(rnk)); memset(sa, 0, sizeof(sa)); memset(height, 0, sizeof(height));
|
|||
|
memset(tmp, 0, sizeof(tmp)); memset(cnt, 0, sizeof(cnt));
|
|||
|
for (i = 0; i < n; i++) { cnt[rnk[i] = s[i]]++; }
|
|||
|
for (i = 1; i < m; i++) { cnt[i] += cnt[i - 1]; }
|
|||
|
for (i = 0; i < n; i++) { sa[--cnt[rnk[i]]] = i; }
|
|||
|
for (k = 1; k <= n; k <<= 1) {
|
|||
|
for (i = 0; i < n; i++) {
|
|||
|
j = sa[i] - k;
|
|||
|
if (j < 0) { j += n; }
|
|||
|
tmp[cnt[rnk[j]]++] = j;
|
|||
|
}
|
|||
|
sa[tmp[cnt[0] = 0]] = j = 0;
|
|||
|
for (i = 1; i < n; i++) {
|
|||
|
if (rnk[tmp[i]] != rnk[tmp[i - 1]] || rnk[tmp[i] + k] != rnk[tmp[i - 1] + k]) { cnt[++j] = i; }
|
|||
|
sa[tmp[i]] = j;
|
|||
|
}
|
|||
|
memcpy(rnk, sa, n * sizeof(int));
|
|||
|
memcpy(sa, tmp, n * sizeof(int));
|
|||
|
if (j >= n - 1) { break; }
|
|||
|
}
|
|||
|
for (j = rnk[height[i = k = 0] = 0]; i < n - 1; i++, k++) {
|
|||
|
while (k >= 0 && s[i] != s[sa[j - 1] + k]) { height[j] = k--, j = rnk[sa[j] + 1]; }
|
|||
|
}
|
|||
|
}
|
|||
|
//<2F><><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>
|
|||
|
const int N = 1000005;
|
|||
|
const int N_CHAR = 26;
|
|||
|
struct SuffixAutomaton {
|
|||
|
struct Node { Node *fail, *next[N_CHAR]; int val, right; };
|
|||
|
Node mempool[N << 1]; int n_node;
|
|||
|
Node *new_node(int v) {
|
|||
|
Node *p = &mempool[n_node++]; memset(p->next, 0, sizeof(p->next));
|
|||
|
p->fail = 0; p->right = 0; p->val = v; return p;
|
|||
|
}
|
|||
|
Node *root, *last;
|
|||
|
SuffixAutomaton() { clear(); }
|
|||
|
void clear() { root = last = new_node(n_node = 0); }
|
|||
|
void add(int c) {
|
|||
|
Node *p = last, *np = new_node(p->val + 1);
|
|||
|
while (p && !p->next[c]) { p->next[c] = np; p = p->fail; }
|
|||
|
if (!p) { np->fail = root; }
|
|||
|
else {
|
|||
|
Node *q = p->next[c];
|
|||
|
if (p->val + 1 == q->val) { np->fail = q; }
|
|||
|
else {
|
|||
|
Node *nq = new_node(p->val + 1);
|
|||
|
for (int i = 0; i < N_CHAR; i++) { nq->next[i] = q->next[i]; }
|
|||
|
nq->fail = q->fail; q->fail = np->fail = nq;
|
|||
|
while (p && p->next[c] == q) { p->next[c] = nq; p = p->fail; }
|
|||
|
}
|
|||
|
}
|
|||
|
last = np; np->right = 1;
|
|||
|
}
|
|||
|
Node *go(const char *s) {
|
|||
|
Node *p = root; int cL = 0; //<2F><>sƥ<73><C6A5><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>
|
|||
|
for (int i = 0; s[i]; i++) {
|
|||
|
int c = s[i] - 'a';
|
|||
|
if (p->next[c]) { p = p->next[c], ++cL; }
|
|||
|
else {
|
|||
|
while (p && !p->next[c]) { p = p->fail; }
|
|||
|
if (!p) { cL = 0; p = root; }
|
|||
|
else { cL = p->val + 1; p = p->next[c]; }
|
|||
|
}
|
|||
|
}
|
|||
|
return p;
|
|||
|
}
|
|||
|
int d[N << 1]; Node *b[N << 1];
|
|||
|
void toposort() {
|
|||
|
for (int i = 0; i <= n_node; i++) { d[i] = 0; }
|
|||
|
int mx_val = 0;
|
|||
|
for (int i = 0; i < n_node; i++) { mx_val = max(mx_val, mempool[i].val); d[mempool[i].val]++; }
|
|||
|
for (int i = 1; i <= mx_val; i++) { d[i] += d[i - 1]; }
|
|||
|
for (int i = 0; i < n_node; i++) { b[--d[mempool[i].val]] = &mempool[i]; }
|
|||
|
}
|
|||
|
void updateright() {
|
|||
|
toposort();
|
|||
|
for (int i = n_node - 1; i; i--) { b[i]->fail->right += b[i]->right; }
|
|||
|
}
|
|||
|
} sa;
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
struct PalindromicTree {
|
|||
|
int nxt[N][26]; //ָ<><D6B8><EFBFBD>Ĵ<EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><CBBC><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int fail[N]; //<2F><>ʾʧ<CABE><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ڸô<DAB8><C3B4><EFBFBD><EFBFBD>Ըýڵ<C3BD><DAB5><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EEB3A4><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ʾ<EFBFBD>Ľڵ<C4BD>
|
|||
|
int cnt[N]; //<2F><>ʾ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ʾ<EFBFBD>ı<EFBFBD><C4B1>ʲ<EFBFBD>ͬ<EFBFBD>Ĵ<EFBFBD><C4B4>ĸ<EFBFBD><C4B8><EFBFBD>(<28><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>, <20><><EFBFBD><EFBFBD>count<6E><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>)
|
|||
|
int num[N]; //<2F><>ʾ<EFBFBD>Խڵ<D4BD><DAB5><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EEB3A4><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ˵<D2B6>Ϊ<EFBFBD><CEAA><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>β<EFBFBD>Ļ<EFBFBD><C4BB>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int len[N]; //<2F><>ʾ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ʾ<EFBFBD>Ļ<EFBFBD><C4BB>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int S[N]; //<2F><>ʾ<EFBFBD><CABE>i<EFBFBD><69><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>ַ<EFBFBD>(S[0] = -1(<28><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڴ<EFBFBD><DAB4>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ַ<EFBFBD>))
|
|||
|
int last; //ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD>γɵ<CEB3><C9B5><EFBFBD><EEB3A4><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ʾ<EFBFBD>Ľڵ<C4BD>
|
|||
|
int n; //<2F><>ʾ<EFBFBD><CABE><EFBFBD>ӵ<EFBFBD><D3B5>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int tot; //<2F><>ʾ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int newnode(int l) { len[tot] = l; return tot++; }
|
|||
|
void init() {
|
|||
|
memset(nxt, 0, sizeof(nxt)); memset(cnt, 0, sizeof(cnt)); memset(len, 0, sizeof(len));
|
|||
|
newnode(0); newnode(-1); tot = last = n = 0; S[n] = -1; fail[0] = 1;
|
|||
|
}
|
|||
|
int getfail(int x) { //ʧ<><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB3A4>
|
|||
|
while (S[n - len[x] - 1] != S[n]) { x = fail[x]; }
|
|||
|
return x;
|
|||
|
}
|
|||
|
void add(int c) {
|
|||
|
c -= 'a'; S[++n] = c;
|
|||
|
int cur = getfail(last); //ͨ<><CDA8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ƥ<EFBFBD><C6A5>λ<EFBFBD><CEBB>
|
|||
|
if (!nxt[cur][c]) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>û<EFBFBD>г<EFBFBD><D0B3>ֹ<EFBFBD>, ˵<><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µı<C2B5><C4B1>ʲ<EFBFBD>ͬ<EFBFBD>Ļ<EFBFBD><C4BB>Ĵ<EFBFBD>
|
|||
|
int now = newnode(len[cur] + 2); //<2F>½<EFBFBD><C2BD>ڵ<EFBFBD>
|
|||
|
fail[now] = nxt[getfail(fail[cur])][c]; //<2F><>AC<41>Զ<EFBFBD><D4B6><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>failָ<6C><D6B8>, <20>Ա<EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת
|
|||
|
nxt[cur][c] = now; num[now] = num[fail[now]] + 1;
|
|||
|
}
|
|||
|
cnt[last = nxt[cur][c]]++;
|
|||
|
}
|
|||
|
void count() {
|
|||
|
for (int i = tot - 1; i >= 0; i--) { cnt[fail[i]] += cnt[i]; }
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ۼӶ<DBBC><D3B6>ӵ<EFBFBD>cnt, <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>fail[v] = u, <20><>uһ<75><D2BB><EFBFBD><EFBFBD>v<EFBFBD><76><EFBFBD>ӻ<EFBFBD><D3BB>Ĵ<EFBFBD>
|
|||
|
}
|
|||
|
} pat;
|