定义
子串:字符串S的子串r[i..j],i≤j,表示r串中从i到j这一段,也就是顺次排列r[i],r[i+1],…,r[j]形成的字符串。
后缀:后缀是指从某个位置i开始到整个串末尾结束的一个特殊子串。字符串r的从第i个字符开始的后缀表示为Suffix(i),也就是Suffix(i)=r[i..len(r)]。
后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列SA[1],SA[2],……,SA[n],并且保证 Suffix(SA[i])
其它概念
>
* 字符串大小比较:可以直接使用函数strcmp()比较两个字符串大小,而字符串大小只要是比较字符的字典序;
* 名次数组:名次数组Rank[i]保存的是Suffix(i)在所有后缀中从小到大排列的“名次”。
注释:后缀数组是“排第几的是谁?”,名次数组是“你排第几?”。容易看出,后缀数组和名次数组为互逆运算。
http://blog.163.com/zqz_20003/blog/static/2694543020109934758407/
生成后缀数组的代码:
char c[100] = "banana";
char *a[100];
int pstrcmp( const void *p1, const void *p2 )
{
return strcmp( *(char* const *)p1, *(char* const*)p2 );
}
for(i=0; i<strlen(c); i++)
a[i] = c+i;
qsort(a, i, sizeof(a[0]), pstrcmp);
后缀数组的应用:求最长重复子字符串
*输入一个字符串,如何求最大重复出现的字符串呢?比如输入ttabcftrgabcd,输出结果为abc, canffcancd,输出结果为can。
给定一个字符串,求出其最长的重复子串。*
#include<iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MAXN = 5000;
static char c[MAXN], *a[MAXN];
int pstrcmp( const void *p1, const void *p2 )
{
return strcmp( *(char* const *)p1, *(char* const*)p2 );
}
int comlen(char *p, char *q){
int i=0;
while(*p && *q && (*p++ == *q++))
i++;
return i;
}
int main(){
//给后缀数组赋值
int i, maxi, maxlen = -1;
char c[MAXN] = "ttabcftrgabcd";
for(i=0; i<strlen(c); i++)
a[i] = c+i;
qsort(a, i, sizeof(a[0]), pstrcmp);
for(int j=0; j<i-1; j++){
if(comlen(a[j], a[j+1]) > maxlen){
maxlen = comlen(a[j], a[j+1]);
maxi = j;
}
}
printf("%.*s\n", maxlen, a[maxi]);
return 0;
}