真的很奇怪,在其他OJ上交了,速度很快排到第二(最慢一个点80ms)。。但是用内存挺多的。
交USACO的时候,在用了15.8M内存的时候RE了。 我猜是限了16M内存。 看来不能省事……我得去重写了
/* TASK:prefix LANG:C++ */ #include <cstdio> #include <cstring> #include <queue> #include <iostream> using namespace std; char s[220][220], text[200115]; int next[220000]; int stail = 0; struct edge { int v; edge *next; edge() { v = - 1; next = NULL; } edge(int x, edge *p) { v = x; next = p; } }*a[200005]={NULL};//v void init() { while (1) { scanf("%s", s[stail++]); if (s[stail - 1][0] == '.') { -- stail; break; } } int textlen = 0; char ch; while ((ch = getchar()) != EOF) { if (ch == '\n') continue; text[textlen++] = ch; } text[textlen] ='\0'; for (int i = 0; i != 200005; ++ i)a[i] =NULL; } inline void ins(int x, int y) // x可以到y { a[x] = new edge(y, a[x]); } inline void kmp(char *son, char *text, int son_length, int text_length) { int i = 0, j = -1; next[0] = -1; while (i != son_length) { if (j == -1 || son[i] == son[j]) next[++i] = ++j; else j = next[j]; } i = 0, j = 0; while (i != text_length) { if (j == -1 || text[i] == son[j]) ++i, ++j; else j = next[j]; if (j == son_length) //j已经超出范围了 { ins(i - son_length, i); j = next[j]; } } } queue<int>q; bool vis[200005]={0}; void doit() { for (int i = 0; i != stail; ++ i) kmp(s[i], text, strlen(s[i]), strlen(text)); q.push(0); vis[0] = true; while (!q.empty()) { int now = q.front(); q.pop(); for (edge *i = a[now]; i != NULL; i = i -> next) { int will = i -> v; if (!vis[will]) { vis[will] = true; q.push(will); } } } int tmp = strlen(text); for (int i = tmp; i >= 0; -- i) if (vis[i]) {printf("%d\n", i); return;} } int main() { freopen("prefix.in","r",stdin); freopen("prefix.out","w",stdout); init(); doit(); return 0; }
写了一个暴力的…… 然后尼玛这么快? 在BSOJ上居然是第一……(上面的KMP是第三)
Executing... Test 1: TEST OK [0.008 secs, 3896 KB] Test 2: TEST OK [0.008 secs, 3896 KB] Test 3: TEST OK [0.005 secs, 3896 KB] Test 4: TEST OK [0.008 secs, 3896 KB] Test 5: TEST OK [0.005 secs, 3896 KB] Test 6: TEST OK [0.041 secs, 3896 KB]
但是不爆内存了显然~而且速度快。显然是数据弱了……但是实际上如果极限数据,2个算法的时间复杂度应该差不多,毕竟串短……,但是显然后者更节约内存
方法: 从0位置开始,把每个串都匹配一下…… 如果从4位置开始,匹配了一个长度3的串,那么把7塞进队列。 因为5,6根本不用匹配了,因为没有串以他们为结尾……
/* TASK:prefix LANG:C++ */ #include <cstdio> #include <cstring> #include <queue> char s[201][11], text[200005]; int length[201]; bool vis[200005]={1,0}; int stail = 0, textlen=0; inline void init() { while (1) { scanf("%s", s[stail++]); length[stail - 1] = strlen(s[stail - 1]); if (s[stail - 1][0] == '.') { -- stail; break; } } char ch; while ((ch = getchar()) != EOF) { if (ch == '\n') continue; text[textlen++] = ch; } for (int i = 0; i != 15; ++ i) text[textlen++] = '#'; text[textlen] ='\0'; } std::queue<int>q; inline bool check(char *son, char *text, int son_length) { for (int i = 0; i != son_length; ++ i) if (son[i] != text[i]) return false; return true; } inline void doit() { int i, will, ans = 0; q.push(0); while (!q.empty()) { ans = q.front(); q.pop(); for (i = 0; i != stail; ++ i) { will = ans + length[i]; if (vis[will]) continue; if (check(s[i],text+ans, length[i])) { vis[will] = 1; q.push(will); } } } printf("%d\n",ans); } int main() { freopen("prefix.in","r",stdin); freopen("prefix.out","w",stdout); init(); doit(); return 0; }