kmp

#include<stdio.h>
#include<string.h>
#include<iostream>

using namespace std;

void get_next_one(char *a, int *next) {
	int i = 1, j = 0;
	next[1] = 0;
	while (i < a[0] - '0') {
		if (j == 0 || a[i] == a[j]) {
			i++;
			j++;
			next[i] = j;
		}
		else
			j = next[j];
	}
}

//aaaaax的next[]
//i=1   next[1]=0
//i=2   a2a1   next[2]=1
//i=3   a3a2    next[3]=2   因为a[3]=a[2]  j的值保留,j=2
//i=4   a4a3  next[4]=3   j=3
//i=5   a5a4 next[5]=4   j=4
//i=6  j=5    next[6]=5
//aaaaax->next[]=012345


//错误的推论,但是跟下面的get_next的改进动机一致
//i=6  j=next[5]=4    x6-a4   不等   j=next[4]
//i=6  j=3     x6-a3   不等    j=next[3]=2
//i=6   j=2    x6-a2   不等    j=next[2]=1
//i=6   j=1    x6-a1   不等    j=next[1]=0
//i=6   


//|a|a|a|a|b|b|c|d   <i=5>
//         |  
//|a|a|a|a|a|x|     j=5  j开始回溯,j=next[j] 
//  |a|a|a|a|a|x|    j=4 ,然后j=next[4]=3
//    |a|a|a|a|a|x|    j=3
//      |a|a|a|a|a|x|     j=2
//        |a|a|a|a|a|x|      j=1   因为j=1为a,跟i=5的b不同,所以i增加,然后j取next[1]=1
//|a|a|a|a|b|b|c|d   <i=6>    i增加
//           |
//          |a|a|a|a|a|x|  j=1
//可见,中间的那几步都是多余的
//改进后的next数组为
//i=1   next[1]=0   初始化   j=0
//i=2   a2a1  next[2]=next[1]=0  j=1      //如果a[i]==a[j]的时候,j的值就递增
//i=3   j=2 a3a2  next[3]=next[2]=0
//i=4  j=3   a4=a3    next[4]=0
//i=5   j=4  a5=a4   next[5]=0
//i=6  j=5   a6!=a5   next[6]=5
//aaaaax新的next[]=000005

//ababaaaba
//next[1]=0    i=1  j=0
//i++ i=2  j++ j=1    a!=b  next[2]=j=1
//j=next[1]=0
//i++ i=3      j=1    a=a   next[3]=next[1]=0
//    i=4      j=2    b=b    next[4]=next[2]=1
//    i=5      j=3    a=a    next[5]=next[3]=0
//    i=6      j=4    a!=b   next[6]=4
//j=next[4]=1    因为a[6]=a  a[1]=a
//    i=7      j=2    a!=b   next[7]=2
//j=next[2]=1   a[7]=a    a[1]=a
//    i=8      j=2    b=b   next[8]=next[2]=1
//    i=9      j=3    a=a    next[9]=next[3]=0
//ababaaaba->next[]=010104210
void get_next(char *a, int *next) {
	int i = 1, j = 0;
	next[1] = 0;
	while (i < a[0]-'0') {
		if (j == 0 || a[i] == a[j]) {
			i++;
			j++;
			if (a[i] != a[j])
				next[i] = j;
			else
				next[i] = next[j];
		}
		else
			j = next[j];
	}
}

int index_kmp(char *A, char *a, int *next, int pos) {
	int i = pos;
	int j = 1;
	while (i <= A[0]-'0' && j <= a[0]-'0') {
		if (A[i] == a[j] || j == 0) {
			i++;
			j++;
		}
		else
			j = next[j];
	}
	if (j > a[0]-'0')
		return i - (a[0]-'0');
	else
		return 0;
}

#define MAX 100

int main() {
	char A[MAX], a[MAX];
	int next[MAX];
	scanf("%s %s", A, a);
	int Alen = strlen(A);
	int alen = strlen(a);
	cout << Alen << "dddd" << alen << endl;
	int i;
	for (i = Alen - 1; i >= 0; i--)
		A[i + 1] = A[i];
	for (i = alen - 1; i >= 0; i--)
		a[i + 1] = a[i];
	A[Alen + 1] = '\0';
	a[alen + 1] = '\0';
	cout << A << endl;
	cout << a << endl;
	A[0] = Alen+'0';
	a[0] = alen+'0';   
	cout << A[0] << "dddd" << a[0] << endl;
	next[0] = alen;
	get_next(a, next);
	next[alen + 1] = '\0';
	int t = 0;
	while (t <= alen) {
		cout << next[t] << "";
		t++;
	}
        cout << endl;
        printf("%d\n", index_kmp(A, a, next, 1));
        return 0;
}





#include<stdio.h>
#include<stdlib.h>
#include<string.h>


int index(char s[], char p[]) {
	int slen = strlen(s);
	int plen = strlen(p);
	int is=0, jp=0;
	while (is < slen && jp < plen) {
		if (s[is] == p[jp]) {
			is++;
			jp++;
		}
		else {
			is = is - jp + 1;
			jp = 0;
		}
			
	}
	if (jp > plen)
		return is - jp; //return is-plen;
	return -1;
}

#define MAX 101

//比如cdcda     a[4]=cdcda   next[4]=00120  
//后面的和前面的进行比较,后面用i表示,前面的用j索引
//d和c   c和c 相同d和d    a和c
//adsfadsfe        d-a   s-a   f-a   a-a d-d s-s f-f    e-a
//多条件控制
//a[i]==a[j]--后面的和前面的相等时候,cdc,a[j=1]=c  a[i=4]=c   继续递增比较
//j==0--后面和前面不想等时候进入比较流程
//while结构,可以在循环里干其他事情,只要迭代值不增加;比如迭代5次对应5个元素的比较,可以在每一次之后进行一个j=next[j]但是迭代值i不增加
//默认都是0,只有满足后面的等于前面的,才会修改这个值,否则自动循环下去,知道迭代完成


void get_next(int *next, char *a, int la) {
	int i = 1, j = 0;
	next[1] = 0;
	while (i <= la) {
		if (a[i] == a[j] || j == 0) {   //当前i和第一个不相同时候靠j==0去判断后一个和第一个;相同时,靠a[i]==a[j]去判断,后一个和第二个,j的值保留
			j++;
			i++;
			if (a[i] == a[j])         //
				next[i] = j;
		}
		else
			j = next[j];
	}
}
//a|b|c|a|b|a|b|c   <i=6>
//          |
//a|b|c|a|b|x| 
// |a|b|c|a|b|x     回溯i=2
//   |a|b|c|a|b|x    i=3
//     |a|b|c|a|b|x   i=4
//     |a|b|c|a|b|x    i=5

//a|b|c|a|b|a|b|c     <i=6>
//          |
//     |a|b|c|a|b|x   i=6
//回溯后发现,是在j=3的时候跟i=6的元素进行比较,相当于j=next[j]
int str_kmp(int *next, char *A, char *a, int lA, int la) {
	int i=1, j=1, k;
	while (i <= lA&&j <= la) {
		if (A[i] == a[j] || j == 0) {
			i++;
			j++;
		}
		else
			j = next[j];
	}
	if (j > la)
		return i - j + 1;
	else
		return -1;
}

int main() {
	int n, k;
	int next[MAX] = { 0 };
	int lA=0, la = 0;
	char A[MAX], a[MAX];
	scanf("%s %s", A, a);
	lA = strlen(A);
	la = strlen(a);
	for (k = la - 1; k >= 0; k--) {
		a[k + 1] = a[k];
	}
	for (k = lA - 1; k >= 0; k--) {
		A[k + 1] = A[k];
	}

	get_next(next, a, la);
	for (n = 1; n < MAX; n++)
		printf("%d ", next[n]);
	putchar('\n');
	k = str_kmp(next, A, a, lA, la);
	if (-1 == k)
		printf("No so");
	else
		printf("%d", k);
	return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值