【USACO2.3.1】最长前缀 KMP(爆内存) 暴力(居然更快还AC)

来源:互联网 发布:linux tomcat安装版 编辑:程序博客网 时间:2024/05/22 14:34

真的很奇怪,在其他OJ上交了,速度很快排到第二(最慢一个点80ms)。。但是用内存挺多的。 


交USACO的时候,在用了15.8M内存的时候RE了。 我猜是限了16M内存。  看来不能省事……我得去重写了


/*TASK:prefixLANG: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};//vvoid 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:prefixLANG: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;}


0 0