这俩天悲剧的紧, 腿扯破点皮还感染了,==!
不过考试结束了,赶紧来一发,依然SAM,但这题标程和测试数据都有点问题,关键就是在于处理神牛id会出现某个神牛id是另一神牛id的前缀的情况,正确的处理方法是对神牛id建立trie,然后在trie上dfs,发现了一个id后就return,这样就保证了不会重复计数,爱神博客上的标程处理方法有问题。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; const int MAXN(100010); const int SIGMA_SIZE(26); const int MAXM(110); const int MAXE(300010); const int MAXH(18); const int INFI((INT_MAX-1) >> 1); const int MOD(2012); const ULL BASE(31); const ULL LIM(1000000000000000ull); inline int idx(char temp) { return temp-'a'; } int cnt[MAXN]; int buc[MAXN << 1]; struct SAM { struct NODE { int len; LL rec; NODE *ch[SIGMA_SIZE], *f; }; NODE pool[MAXN << 1]; int size; NODE *root, *last; void init() { root = last = pool; root->len = 0; root->f = 0; root->rec = 0; memset(root->ch, 0, sizeof(root->ch)); size = 1; } NODE *newnode(int tl) { pool[size].len = tl; pool[size].rec = 1; memset(pool[size].ch, 0, sizeof(pool[size].ch)); return pool+size++; } void extend(int id) { NODE *p = last, *np = newnode(last->len+1); last = np; while(p && p->ch[id] == 0) p->ch[id] = np, p = p->f; if(p == 0) np->f = root; else { NODE *q = p->ch[id]; if(p->len+1 == q->len) np->f = q; else { NODE *nq = newnode(p->len+1); memcpy(nq->ch, q->ch, sizeof(nq->ch)); nq->f = q->f; q->f = np->f = nq; while(p && p->ch[id] == q) p->ch[id] = nq, p = p->f; } } } void turpo() { memset(cnt, 0, sizeof(cnt[0])*(last->len+1)); for(int i = 0; i < size; ++i) ++cnt[pool[i].len]; for(int i = 1; i <= last->len; ++i) cnt[i] += cnt[i-1]; for(int i = 0; i < size; ++i) buc[--cnt[pool[i].len]] = i; } void fun() { for(int i = size-1; i >= 0; --i) { NODE *p = pool+buc[i]; for(int j = 0; j < SIGMA_SIZE; ++j) if(p->ch[j]) p->rec += p->ch[j]->rec; } } }; SAM sam; LL ans; struct TRIE { int ch[10010][SIGMA_SIZE]; bool val[10010]; int size; void init() { memset(ch[0], 0, sizeof(ch[0])); val[0] = false; size = 1; } void insert(char *S) { int u = 0, id; for(; *S; ++S) { id = idx(*S); if(!ch[u][id]) { memset(ch[size], 0, sizeof(ch[size])); val[size] = false; ch[u][id] = size++; } u = ch[u][id]; } val[u] = true; } void dfs(int u, SAM::NODE *p) { if(val[u]) { ans += p->rec; return; } for(int i = 0; i < SIGMA_SIZE; ++i) if(ch[u][i] && p->ch[i]) dfs(ch[u][i], p->ch[i]); } }; TRIE trie; void revs(char *S, int len) { int i = 0, j = len-1; while(i < j) swap(S[i++], S[j--]); } char str[MAXN]; int main() { while(~scanf("%s", str)) { int len = strlen(str); revs(str, len); sam.init(); for(int i = 0; i < len; ++i) sam.extend(idx(str[i])); sam.turpo(); sam.fun(); trie.init(); int n; scanf("%d", &n); for(int i = 0; i < n; ++i) { scanf("%s", str); revs(str, strlen(str)); trie.insert(str); } ans = 0; trie.dfs(0, sam.root); printf("%lld\n", ans); } return 0; }