题目:
题解:
#define SIZE 9470
#define N 168000
#define P 13331
typedef unsigned long long ULL;
ULL p[301];//p[i]存储P^i
void init()//初始化p进制次幂数组
{
int i;
p[0]=1;
for(i=1;i<300;i++)
{
p[i]=p[i-1]*P;
}
}
int** palindromePairs(char**words, int wordsSize, int* returnSize, int** returnColumnSizes){
int **re=(int **)malloc(sizeof(int *)*N);
*returnColumnSizes=(int *)malloc(sizeof(int)*N);
int i,j,k;
int index=0;
int len;
int l,r;
int hash[SIZE];//存储某字符串hash值在words中的对应下标
ULL key[SIZE];//存储字符串hash值,可近似认为字符串与hash值之间是一一对应的
ULL t;
ULL pre[301];//存储前缀字符串hash值,pre下标从1开始(即pre[i]存储某字符串前i个子字符串的哈希值),注意下标转换
char *word=NULL;
init();//初始化p数组
memset(hash,-1,sizeof(hash));
for(i=0;i<wordsSize;i++)
{
t=0;
word=words[i];
for(j=strlen(word)-1;j>=0;j--)//倒序遍历计算哈希值t
{
t=t*P+word[j];
}
//第二层哈希,将hash值及对应下标存入哈希表
j=t%SIZE;
while(hash[j]!=-1)
{
j=(j+1)%SIZE;
}
hash[j]=i;
key[j]=t;
}
for(i=0;i<wordsSize;i++)
{
word=words[i];
len=strlen(word);
pre[0]=0;
for(j=0;j<len;j++)//计算前缀哈希值数组
{
pre[j+1]=pre[j]*P+word[j];
}
for(j=-1;j<len;j++)//正向查找回文串
{
for(l=0,r=j;l<r;l++,r--)
{
if(word[l]!=word[r])
{
break;
}
}
if(l>=r)//下标0-j是一个回文串,查找原字符串数组中是否存在j+1-末尾的翻转字符串
{
t=pre[len]-pre[j+1]*p[len-j-1];//j+1-末尾子字符串的哈希值
k=t%SIZE;
while(hash[k]!=-1&&key[k]!=t)
{
k=(k+1)%SIZE;
}
if(hash[k]>=0&&hash[k]!=i)//找到了且不是自身
{
re[index]=(int *)malloc(sizeof(int)*2);
re[index][0]=hash[k];
re[index][1]=i;
returnColumnSizes[0][index++]=2;
if(words[hash[k]][0]==0)//空字符串,特处
{
re[index]=(int *)malloc(sizeof(int)*2);
re[index][0]=i;
re[index][1]=hash[k];
returnColumnSizes[0][index++]=2;
}
}
}
}
for(j=len-1;j>0;j--)//反向查找回文串
{
for(l=j,r=len-1;l<r;l++,r--)
{
if(word[l]!=word[r])
{
break;
}
}
if(l>=r)//下标j-末尾子字符串是回文串
{
t=pre[j];//前j-1个子字符串的hash值
k=t%SIZE;
while(hash[k]!=-1&&key[k]!=t)
{
k=(k+1)%SIZE;
}
if(hash[k]>=0&&hash[k]!=i)//找到了且不是自身
{
re[index]=(int *)malloc(sizeof(int)*2);
re[index][0]=i;
re[index][1]=hash[k];
returnColumnSizes[0][index++]=2;
}
}
}
}
*returnSize=index;
return re;
}