这是有问题的问题:http://www.codechef.com/problems/SSTORY [竞争规划]
TLDR:给定两个字符串,找到最大的公共子字符串。
我想我可以在改变(通过BS)匹配长度上使用Rabin-Karp算法。因此,我为length=current_B
上的每个子字符串创建了一个哈希(它将采用O(len(S1))
)并将其与S2 O(len(S2))
的每个子字符串进行匹配。由于约束条件为2.5 * 10 ^ 5,因此应该可以在2秒的时间限制内轻松运行。
我的第一种方法是使用双重散列(以减少碰撞):
(查看最后一个,因为那是最新的;这可能没有上面那个错误。)
http://www.codechef.com/viewsolution/6986274
http://www.codechef.com/viewsolution/6986284
然而,所有返回的TLE。
我在这里阅读(http://apps.topcoder.com/forums/wiki/x/aoE_/?module=Thread&threadID=826779&mc=7&view=tree),TLE的原因可能是将成对推入一组(显然可能代价高昂)。用户建议使用链接列表(我从http://www.algolist.net/Data_structures/Hash_table/Chaining获得)。
我使用链接列表重新实现了相同的算法并提交了:
#include <cstdio>
#include <string>
#include <iostream>
#include <cstring>
using namespace std;
#define MOD 1000000007
#define HVAL 23
class LinkedHashEntry {
private:
int key;
string value;
LinkedHashEntry *next;
public:
LinkedHashEntry(int key, string value)
{
this->key = key;
this->value = value;
this->next = NULL;
}
int getKey()
{
return key;
}
string getValue()
{
return value;
}
void setValue(string value)
{
this->value = value;
}
LinkedHashEntry *getNext()
{
return next;
}
void setNext(LinkedHashEntry *next)
{
this->next = next;
}
};
#define TABLE_SIZE 128
class HashMap
{
private:
LinkedHashEntry **table;
public:
HashMap()
{
table = new LinkedHashEntry*[TABLE_SIZE];
for (int i = 0; i < TABLE_SIZE; i++)
table[i] = NULL;
}
int get(int key)
{
int hash = (key % TABLE_SIZE);
if (table[hash] == NULL)
return 0;
else
{
LinkedHashEntry *entry = table[hash];
while (entry != NULL && entry->getKey() != key)
entry = entry->getNext();
if (entry == NULL)
return 0;
else
return 1;
}
}
void put(int key, string value)
{
int hash = (key % TABLE_SIZE);
if (table[hash] == NULL)
table[hash] = new LinkedHashEntry(key, value);
else
{
LinkedHashEntry *entry = table[hash];
while (entry->getNext() != NULL)
entry = entry->getNext();
if (entry->getKey() == key)
entry->setValue(value);
else
entry->setNext(new LinkedHashEntry(key, value));
}
}
void remove(int key)
{
int hash = (key % TABLE_SIZE);
if (table[hash] != NULL)
{
LinkedHashEntry *prevEntry = NULL;
LinkedHashEntry *entry = table[hash];
while (entry->getNext() != NULL && entry->getKey() != key)
{
prevEntry = entry;
entry = entry->getNext();
}
if (entry->getKey() == key)
{
if (prevEntry == NULL)
{
LinkedHashEntry *nextEntry = entry->getNext();
delete entry;
table[hash] = nextEntry;
}
else
{
LinkedHashEntry *next = entry->getNext();
delete entry;
prevEntry->setNext(next);
}
}
}
}
~HashMap()
{
for (int i = 0; i < TABLE_SIZE; i++)
{
if (table[i] != NULL)
{
LinkedHashEntry *prevEntry = NULL;
LinkedHashEntry *entry = table[i];
while (entry != NULL)
{
prevEntry = entry;
entry = entry->getNext();
delete prevEntry;
}
}
}
delete[] table;
}
};
#define DEBUG 0
int h[250009];
int cnt;
int pt[250009];
string s, b;
inline int mod(int x, int y=MOD)
{
return (x%y+y)%y;
}
void hash(string s)
{
if(s.length()==0)
{
h[cnt]=0;
return;
}
if(s.length()==1)
{
h[cnt]=s.at(0);
return;
}
char x=s.at(0), y=s.at(s.length()-1);
if(DEBUG) cout << "x=" << x << "; y=" << y << "; ";
if(cnt)
{
if(DEBUG) printf("h[cnt]=%d; ", h[cnt]);
if(DEBUG) printf("h[cnt-1]=%d; ", h[cnt-1]);
h[cnt]=mod(h[cnt-1]-mod((x-'a'+1)*pt[s.length()-2]))*HVAL+y-'a'+1;
h[cnt]=mod(h[cnt]);
}
else
{
h[cnt]=0;
for(int i=0; i<s.length(); i++)
{
h[cnt]*=HVAL;
h[cnt]=mod(h[cnt], MOD);
h[cnt]+=s.at(i)-'a'+1;
h[cnt]=mod(h[cnt], MOD);
}
}
}
int main()
{
if(DEBUG) freopen("SSTORY.in", "r", stdin);
HashMap hashes;
cin >> b >> s;
int ls=s.length(), lb=b.length();
int low=0, high=ls+1, mid=(low+high)/2;
int ans, ansLen=0, minI=lb+2;
pt[0]=1;
for(int i=1; i<=lb; i++)
{
pt[i]=pt[i-1]*HVAL;
pt[i]=mod(pt[i], MOD);
}
while(low<high)
{
memset(h, 0, sizeof(h));
int ol=low, oh=high, om=mid;
int flag=0;
cnt=0;
for(int i=0; i+mid<=lb; i++)
{
if(DEBUG) printf("hash(b.substr(%d, %d))=", i-(i>0), mid+(i>0));
hash(b.substr(i-(i>0), mid+(i>0)));
if(DEBUG) cout << "hash(" << b.substr(i-(i>0), mid+(i>0)) << ")=" << h[cnt] << endl;
hashes.put(h[cnt], b.substr(i-(i>0), mid+(i>0)));
cnt++;
}
cnt=0;
for(int i=0; i+mid<=ls; i++)
{
hash(s.substr(i-(i>0), mid+(i>0)));
if(DEBUG) printf("Checking ");
if(DEBUG) printf("hash(s.substr(%d, %d))=", i-(i>0), mid+(i>0));
if(DEBUG) cout << "hash(" << s.substr(i-(i>0), mid+(i>0)) << ")=" << h[cnt] << endl;
if(hashes.get(h[cnt]) && mid!=0 && (minI>ans || ansLen<mid))
{
if(DEBUG) cout << "^ WORKING" << endl;
ans=minI=i;
ansLen=mid;
flag=1;
}
cnt++;
}
if(flag)
low=mid;
else
high=mid;
mid=(low+high)/2;
if(low==ol && high==oh && mid==om)
break;
}
if(ansLen<=0)
printf("0\n");
else
{
cout << s.substr(ans, ansLen);
printf("\n%d\n", ansLen);
}
return 0;
}
两者都导致SIGABRT(可能是某些访问,例如s.at(-1)
或其他)。
你能在我的代码中找到错误吗?我已经解决了这个问题3天了:/谢谢:)