几个算法
来源:互联网 发布:tensorflow alphago 编辑:程序博客网 时间:2024/04/28 00:43
一、矩阵相乘动态规划
1.基本思想
在比较基本的算法设计思想里,动态规划是比较难于理解,难于抽象的一种,但是却又十分重要。动态规划的实质是分治思想和解决冗余,因此它与分治法和贪心法类似,它们都是将问题的实例分解为更小的、相似的子问题,但是动态规划又有自己的特点。
贪心法的当前选择可能要依赖于已经作出的选择,但不依赖于还未做出的选择和子问题,因此它的特征是由顶向下,一步一步地做出贪心选择,但不足的是,如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最优解。相比而言,动态规划则可以处理不具有贪心实质的问题。
在用分治法解决问题时,由于子问题的数目往往是问题规模的指数函数,因此对时间的消耗太大。动态规划的思想在于,如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,如果我们能够保存已经解决的子问题的答案,而在需要的时候再找出已求得的答案,这样就可以避免大量的重复计算。由此而来的基本思路是,用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。
比较感性的说,其实动态规划的思想是对贪心算法和分治法的一种折衷,它所解决的问题往往不具有可爱的贪心实质,但是各个子问题又不是完全零散的,这时候我们用一定的空间来换取时间,就可以提高解题的效率。
2.程序
#include "iostream.h"
#include "stdio.h"
#define N 5
void Traceback(int i,int j,int s[][N])
{
if(i==j)return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
cout<<"Multiply A"<<i<<","<<s[i][j];
cout<<"and A"<<(s[i][j]+1)<<","<<j<<endl;
}
void MatrixChain(int *p,int n,int m[][N],int s[][N])
{ int i,r,j,k,t;
for(i=1;i<=n;i++)m[i][i]=0;
for(r=2;r<=n;r++)
for(i=1;i<=n-r+1;i++)
{j=i+r-1;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(k=i+1;k<j;k++)
{ t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j])
{m[i][j]=t;
s[i][j]=k;
}
}
}
}
void main()
{
cout<<"动态规划求矩阵连乘计算次序最优解:/n";
int s[N][N];
int p[N];
int m[N][N];
int i;
cout<<"初始化N=5个矩阵行列数:/n";
for(i=0;i<N;i++)
cin>>p[i];
cout<<"输出结果:/n";
MatrixChain(p,N,m,s);
Traceback(1,N,s);
}
3.结果
二.分治法同时求最大元最小元
1.分治法的基本思想
任何一个可以用计算机求解的问题所需的计算时间都与其规模N有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算;n=2时,只要作一次比较即可排好序;n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
如果原问题可分割成k个子问题(1<k≤n),且这些子问题都可解,并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
2.程序
//******************************************
//用分治法同时求最大元和最小元
//******************************************
#include "iostream.h"
#define N 10
int max(int a,int b)
{
return((a>b)?a:b);
}
int min(int a,int b)
{
return((a<b)?a:b);
}
void Search(int a[],int *max0,int *min0,int n)
{int g[30];
int i,m;
int max1,max2,min1,min2;
if(n==1)
{*max0=a[0];
*min0=a[0];
}
else if(n==2)
{*max0=max(a[0],a[1]);
*min0=min(a[0],a[1]);
}
else
{ m=n/2;
for(i=0;i<m;i++)
g[i]=a[i];
Search(g,&max1,&min1,m);
for(i=0;i<n-m;i++)
g[i]=a[i+m];
Search(g,&max2,&min2,n-m);
*max0=max(max1,max2);
*min0=min(min1,min2);
}
}
void main()
{ cout<<"用分治法同时求最大元和最小元/n";
int a[N];
int i,max,min;
cout<<"输入"<<N<<"个数:/n";
for(i=0;i<N;i++)
cin>>a[i];
Search(a,&max,&min,N);
cout<<"输出结果:/n";
cout<<"max="<<max<<"/n";
cout<<"min="<<min<<"/n";
}
3.结果
三.分治法求最大元次大元
1.分治法的基本思想(同上)
2.程序
//******************************************
//用分治法同时求最大元和次大元
//******************************************
#include "iostream.h"
#define N 10
int max(int a,int b)
{
return((a>b)?a:b);
}
int min(int a,int b)
{
return((a<b)?a:b);
}
void Search(int a[],int *max0,int *second0,int n)
{int g[30];
int i,m;
int max1,max2,second1,second2;
if(n==1)
{*max0=a[0];
*second0=a[0];
}
else if(n==2)
{*max0=max(a[0],a[1]);
*second0=min(a[0],a[1]);
}
else
{ m=n/2;
for(i=0;i<m;i++)
g[i]=a[i];
Search(g,&max1,&second1,m);
for(i=0;i<n-m;i++)
g[i]=a[i+m];
Search(g,&max2,&second2,n-m);
*max0=max(max1,max2);
*second0=max(min(max1,max2),max(second1,second2));
}
}
void main()
{ cout<<"用分治法同时求最大元和次大元/n";
int a[N];
int i,max,second;
cout<<"输入"<<N<<"个数:/n";
for(i=0;i<N;i++)
cin>>a[i];
Search(a,&max,&second,N);
cout<<"输出结果:/n";
cout<<"max="<<max<<"/n";
cout<<"second="<<second<<"/n";
}
3.结果
四: 冒泡排序
1. 基本思想:
比较相邻两个记录的关键字,若r[i].key>r[i+1].key,则交换之,其中i 从0到n-pass-1(pass的初值为1)称之为一趟起泡排序, 其结果是使最大关键字的记录被交换到n-pass的位置上。
如果某一趟起泡排序过程中没有进行一次记录的交换,则排序过程结束。最坏情况下需n-1趟排序。
若记录序列的初始状态为"正序",则冒泡排序过程只需进行一趟排序,在排序过程中只需进行n-1次比较,且不移动记录;反之,若记录序列的初始状态为"逆序",则需进行n(n-1)/2次比较和记录移动。因此冒泡排序总的时间复杂度为O(n*n)。
2.程序
//********************************************************
//冒泡排序
//********************************************************
#include "stdio.h"
#include "stdlib.h"
#define N 10000
void main()
{
int i,j,count=0;
int a[N], t;
//随机产生N个数
for(i=0;i<N;i++)
a[i]= rand();
//排序
for(i=0;i<N-1;i++)
for(j=0;j<N-i-1;j++)
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
//每行五列输出有序数
for(i=0;i<N;i++)
{
if(count%5==0)printf("/n");
count++;
printf("%10d",a[i]);
}
printf("/n");
}
3.结果
五.快速排序
1.基本思想:
首先选取一个记录作为枢轴(不失一般性,可选第一个记录),依它的关键字为基准重排其余记录,将所有关键字比它大的记录都排在它之后,而将所有关键字比它小的记录都排在它之前,由此完成一趟快速排序。之后,分别对由一趟排序分割而成的两个子序列进行快速排序。时间复杂度O(nlogn).
2.程序
//**********************************************************
//快速排序
//**********************************************************
#include "stdio.h"
#include "stdlib.h"
#define N 10000
int Partition(int a[],int low,int high);
void QuikSort(int a[],int low,int high);
void main()
{
int i,count=0;
int a[N];
//随机产生N个数
for(i=0;i<N;i++)
a[i]= rand();
//堆排序
QuikSort(a,0,N-1);
//每行五列输出有序数
for(i=0;i<N;i++)
{
if(count%5==0)printf("/n");
count++;
printf("%10d",a[i]);
}
printf("/n");
}
//递归调用实现快速排序
void QuikSort(int a[],int low,int high)
{
if(low<high)
{
int q=Partition(a,low,high);
QuikSort(a,low,q-1);
QuikSort(a,q+1,high);
}
}
//交换顺序表a中low到high数值,实现枢轴前(后)不大(小)于它
int Partition(int a[],int low,int high)
{
int q=a[low];
while(low<high)
{
while(low<high&&a[high]>=q)
--high;
a[low]=a[high];
while(low<high&&a[low]<=q)
++low;
a[high]=a[low];
}
a[low]=q;
return low;
}
3.结果
六.堆排序
1.分析设计思想:
首先将初始待排序记录序列建堆,则堆顶元素必为含最大关键字或最小关键字的记录,输出该记录,然后将剩余记录再调整为堆,如此反复,直至排序结束。
在堆排序主要需解决两个问题:
① 如何建堆? 在完全二叉树中,所有序号i>└n/2┘的结点都是叶子,因此,以这些结点为根的子树均已是堆,这样只需将以序号为└n/2┘, └n/2┘-1, └n/2┘-2,…,1的结点为根、的子树都调整为堆即可。在按此次序调整每个结点时,其左、右子树均已是堆。
② 若ki的左、右子树已经是堆,如何将以ki为根的完全二叉树也调整为堆? 因ki的左、右子树已经是堆,所以必须在ki 和它的左、右孩子中选出最小(或最大)的结点放到ki的位置上,不妨设k2I关键字最小,将ki与k2I交换位置,而交换之后有可能导致以k2I为根的子树不再为堆,于是可重复上述过程,将以k2I为根的子树调整为堆,……,如此逐层下去,最多可能一直调整到树叶,此方法称为"筛选法"。
2.程序
//*******************************************************
//堆排序
//*******************************************************
#include <dos.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100000 //排序表的最大容量
typedef struct //定义排序表的结构
{int elemword[MAXSIZE]; //数据元素关键字
int length; //表中当前元素的个数
}SqList;
void InitialSqList(SqList&); //初始化排序表
void HeapSort(SqList &); //堆排序
void HeapAdjust(SqList &,int,int); //堆调整
void PrintSqList(SqList); //显示表中的所有元素
void main()
{SqList L; //声明表L
char j='y';
//-------------------------程序说明-------------------------------
printf("本程序将演示堆排序的操作。/n");
//----------------------------------------------------------------
while(j!='n'&&j!='N')
{InitialSqList(L); //待排序列初始化
HeapSort(L); //堆排序
PrintSqList(L); //显示排序结果
printf("继续进行下一次排序吗?(Y/N)");
scanf(" %c",&j);
}
printf("程序运行结束!/n按任意键关闭窗口!/n");
getchar();getchar();
}
void InitialSqList(SqList &L)
{//表初始化
int i;
printf("请输入待排序的记录的个数:");
scanf("%d",&L.length);
for(i=1;i<=L.length;i++)
L.elemword[i]= rand();
printf("输出待排序的记录的关键字(整型数):/n");
for(i=1;i<=L.length;i++)
{printf("%10d",L.elemword[i]);
if(i%5==0)printf("/n");
}
}
void HeapSort(SqList &L)
{//对顺序表L做堆排序。
int i,t;
for(i=L.length/2;i>0;--i) //把L.elemword[1..L.length]建成大顶堆
HeapAdjust(L,i,L.length);
for(i=L.length;i>1;--i)
{t=L.elemword[1]; //将堆顶记录和当前未经排序子序列L.elemword[1..i]
L.elemword[1]=L.elemword[i]; //中的最后一个记录相互交换
L.elemword[i]=t;
HeapAdjust(L,1,i-1); //将L.r[1..i-1]重新调整为大顶堆
}
}
void HeapAdjust(SqList &H,int s,int m)
{//已知H.elemword[s..m]中除H.elemword[s]之外均满足堆的定义,本函数调整H.elemword[s]
//使H.elemword[s..m]成为一个大顶堆
int j,rc;
rc=H.elemword[s];
for(j=2*s;j<=m;j*=2) //沿关键字叫大的结点向下筛选
{if(j<m&&H.elemword[j]<H.elemword[j+1]) ++j; //j为关键字较大的记录的下标
if(rc>=H.elemword[j]) break; //rc应插入在位置s上
H.elemword[s]=H.elemword[j];
s=j;
}
H.elemword[s]=rc; //插入
}
void PrintSqList(SqList L)
{//显示表中所有元素
int i;
printf("已排好序的序列如下:/n");
for(i=1;i<=L.length;i++)
{printf("%10d",L.elemword[i]);
if(i%5==0)printf("/n");
}
printf("/n");
}
3.结果
七.基数排序
1.基本思想
实现排序主要是通过关键字间的比较和移动记录这两种操作,而实现基数排序不需要进行记录关键字间的比较,它是一种利用多关键字排序的思想,即借助"分配"和"收集"两种操作对单逻辑关键字进行排序的方法。
基数排序的方法是:一个逻辑关键字可以看成由若干个关键字复合而成的,可把每个排序关键字看成是一个d元组:
例如,如果关键字是数值,且其值在0~99范围内,则可把每一个十进制数字看成是一个关键字,即可认为K由2个关键字(K0,K1)组成,其中K0是十位数,K1是个位数。排序时先按 的值从小到大将记录分配到r个盒子中,然后依次收集这些记录,再按 的值分配到r个盒子中,如此反复,直到对分配后收集起来的序列,便是完全排序的状态,其中r称为基数。这个过程是按LSD(最低位优先法)进行排序的,即从最低数位关键字起,按关键字的不同值对序列中记录"分配"和"收集"的。基数的选择和关键字的分解法因关键字的类型而异。
为了实现记录的"分配"和"收集",需设立r个队列,排序前将队列设置为空,分配时,将记录插入到各自的队列中去,收集时将这些队列中记录排在一起。
一般采用静态链表作为记录序列的存储结构,并且不另外设置各链队列的结点空间,而是利用静态链表中的结点作为链队列中的结点,这样只需修改指针即可完?quot;分配"和"收集"任务。时间复杂度为O(d(n+rd))
在基数排序算法中,没有进行关键字的比较和记录的移动,而只是顺链扫描链表和进行指针赋值,所以,排序的时间主要耗费在修改指针上。对于n个记录(假设每个记录含d个关键字,每个关键字的取值范围为rd个值)进行一趟分配的时间复杂度为O(n),进行一趟收集的时间复杂度为O(rd),整个排序过程需要进行d趟分配和收集操作。因此,链式基数排序总的时间复杂度为O(d(n+rd))。
当n较小,d较大时,基数排序并不合适。只有当n较大,d较小时,特别是记录的信息量较大时,基数排序最为有效。基数排序中所需辅助空间为2rd个队列指针,另外每个记录中都增加了一个指针域。
2.程序
#include <iostream.h>
#include <iomanip.h>
// constant size must be defined as the array size for bucketSort to work
const int SIZE = 12;
void bucketSort( int [] );
void distributeElements( int [], int [][ SIZE ], int );
void collectElements( int [], int [][ SIZE ] );
int numberOfDigits( int [], int );
void zeroBucket( int [][ SIZE ] );
int main()
{
int array[ SIZE ] = { 19, 13, 5, 27, 1, 26, 31, 16, 2, 9, 11, 21 };
cout << "Array elements in original order:/n";
for ( int i = 0; i < SIZE; ++i )
cout << setw( 3 ) << array[ i ];
cout << '/n';
bucketSort( array );
cout << "/nArray elements in sorted order:/n";
for ( int j = 0; j < SIZE; ++j )
cout << setw( 3 ) << array[ j ];
cout << endl;
return 0;
}
// Perform the bucket sort algorithm
void bucketSort( int a[] )
{
int totalDigits, bucket[ 10 ][ SIZE ] = { 0 };
totalDigits = numberOfDigits( a, SIZE );
for ( int i = 1; i <= totalDigits; ++i ) {
distributeElements( a, bucket, i );
collectElements( a, bucket );
if ( i != totalDigits )
zeroBucket( bucket ); // set all bucket contents to zero
}
}
// Determine the number of digits in the largest number
int numberOfDigits( int b[], int arraySize )
{
int largest = b[ 0 ], digits = 0;
for ( int i = 1; i < arraySize; ++i )
if ( b[ i ] > largest )
largest = b[ i ];
while ( largest != 0 ) {
++digits;
largest /= 10;
}
return digits;
}
// Distribute elements into buckets based on specified digit
void distributeElements( int a[], int buckets[][ SIZE ], int digit )
{
int divisor = 10, bucketNumber, elementNumber;
for ( int i = 1; i < digit; ++i ) // determine the divisor
divisor *= 10; // used to get specific digit
for ( int k = 0; k < SIZE; ++k ) {
// bucketNumber example for hundreds digit:
// (1234 % 1000 - 1234 % 100) / 100 --> 2
bucketNumber = ( a[ k ] % divisor - a[ k ] %
( divisor / 10 ) ) / ( divisor / 10 );
// retrieve value in buckets[bucketNumber][0] to determine
// which element of the row to store a[i] in.
elementNumber = ++buckets[ bucketNumber ][ 0 ];
buckets[ bucketNumber ][ elementNumber ] = a[ k ];
}
}
// Return elements to original array
void collectElements( int a[], int buckets[][ SIZE ])
{
int subscript = 0;
for ( int i = 0; i < 10; ++i )
for ( int j = 1; j <= buckets[ i ][ 0 ]; ++j )
a[ subscript++ ] = buckets[ i ][ j ];
}
// Set all buckets to zero
void zeroBucket( int buckets[][ SIZE ] )
{
for ( int i = 0; i < 10; ++i )
for ( int j = 0; j < SIZE; ++j )
buckets[ i ][ j ] = 0;
}
3.结果
八.2-3树插入
1. 基本思想
2-3树即为三阶B-树, B-树是一种平衡的多路查找树,一棵m阶的B-树,或为空树,或为满足下列特征的m叉树:
①树中每个结点至多有m棵子树;
②若根结点不是叶子结点,则至少有两棵子树;
③除根之外的所有非终端结点至少有棵子树;
④所有的非终端结点中包含下列信息数据:
(n,A0,K1,A1,K2,A2,…,Kn,An)
其中,Ki(i=1,…,n)为关键字,且Ki<Ki+1,Ai为指向子树根结点的指针,且指针Ai-1所指子树中所有结点的关键字均小于Ki,An所指子树中所有结点的关键字均大于Kn,n为关键字的个数。
⑤所有的叶子结点都出现在同一层次上,并且不带信息。
B+树是一种B-树的变形树,具体与B-树的差别见例题。
键树又称数字查找树,它是一棵度≥2的树,树中的每个结点中不是包含一个或几个关键字,而是只含有组成关键字的符号。
2.程序
//****************************************
//2-3树插入程序
//****************************************
#include "iostream.h"
#define m 3 //定义B-树阶数,m=3即为2-3树
#define NULL 0
typedef struct BTNode
{
int keynum;
struct BTNode *parent;
int key[m+1];
struct BTNode *ptr[m+1];
}BTNode,*BTree;
typedef struct
{
BTNode *pt;
int r;
int tag;
}Result;
//查找
Result *Search(struct BTNode *T,int k)
{
struct BTNode *p,*q;
Result *s;
s=NULL;
p=T;
q=NULL;
int i=1,j;
int found=0;
while(p&&!found)
{
while(j<=p->keynum)
{if(k<p->key[i])i++;
else
{i=i-1;
break;
}
j++;
}
if(i>0&&p->key[i]==k)found=1;
else
{q=p;
p=p->ptr[i];
}
}
if(found)
{s->pt=p;
s->r=i;
s->tag=1;
return s;
}
else
{
s->pt=q;
s->r=i;
s->tag=0;
return s;
}
}
//插入
void Insert(struct BTNode *T,int k,struct BTNode *q,int i)
{
struct BTNode *ap,*p,*c;
ap=NULL;
p=NULL;
c=NULL;
int x=k;
int a,s;
int finished=0;
while(q&&!finished)
{ q->key[i+2]=q->key[i+1]; //直接插入
q->key[i+1]=x;
q->ptr[i+2]=q->ptr[i+1];
ap=q->ptr[i];
q->keynum++;
if(q->keynum<m)finished=1;//未溢出,插入成功
else
{ if(m%2==0)
s=m/2;
else
s=m/2+1;
//分裂结点**************************
p=q;
ap->parent=p->parent;
for(a=s;a<p->keynum;a++)
ap->key[a+1-s]=p->key[a+1];
for(a=s;a<=p->keynum;a++)
ap->ptr[a-s]=p->ptr[a];
//**********************************
q=q->parent;
if(q)i=Search(q,x)->r;
}
}
if(!finished)
{ c=new struct BTNode;
c->keynum=1;
c->parent=NULL;
c->key[1]=x;
c->ptr[1]=T;
}
cout<<"插入成功!"<<"/n";
}
void main()
{
cout<<"2-3树插入程序"<<"/n";
int k;
struct BTNode *T;
Result *q;
T=new struct BTNode ;
cout<<"输入待插关键字:"<<"/n";
cin>>k;
q=Search(T, k);
Insert(T, k,q->pt,q->r);
}
九.最优二叉搜索树
1.基本思想
2.程序
//********************************************************************
//最优二叉搜索树
//********************************************************************
#include "iostream.h"
#define N 5
void OptimaBinarySearchTree(int *a,int *b,int n,int m[][N],int s[][N],int w[][N])
{ int i,j,r,k,t;
for(i=0;i<=n;i++)
{
w[i+1][i]=a[i];
m[i+1][i]=0;
}
for(r=0;r<n;r++)
for(i=1;i<=n-r;i++)
{
j=i+r;
w[i][j]=w[i][j-1]+a[j]+b[j];
m[i][j]=m[i+1][j];
s[i][j]=i;
for(k=i+1;k<=j;k++)
{
t=m[i][k-1]+m[k+1][j];
if(t<m[i][j])
{ m[i][j]=t;
s[i][j]=k;
cout<<"最优解:s["<<i<<"]["<<j<<"]="<<s[i][j]<<"/n";
}
}
m[i][j]+=w[i][j];
}
}
void main()
{ cout<<"最优二叉搜索树"<<"/n";
int i;
int a[N],b[N];
int m[N][N],s[N][N],w[N][N];
cout<<"初始化概率数组a["<<N<<"]:/n";
for(i=0;i<N;i++)
cin>>a[i];
cout<<"初始化概率数组b["<<N<<"]:/n";
for(i=1;i<N;i++)
cin>>a[i];
OptimaBinarySearchTree(a,b,N,m,s,w);
}
3.结果
十.模式匹配:
1. 基本思想:
这种算法是D.E.Knuth 与V.R.Pratt和J.H.Morris同时发现的,因此人们称为KMP算法。此算法可以在O(n+m)的时间数量级上完成串的模式匹配操作。
其基本思想是:每当匹配过程中出现字符串比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
假设主串为“s1s2,...sn",模式串为”p1p2...pn",当主串中第i个字符与模式串中第j个字符“失配”(比较不等)时,主串第i字符(i指针不回溯)应与模式中哪个字符再比较?
令当s[i]!=p[j]时,s[i]应与p[next[j]]进行比较。
例如: P="abaabcac"
则
2.程序:
//**************************************************************************
//模式匹配(KMP)程序
//**************************************************************************
#include "iostream.h"
#include "string.h"
#include "stdio.h"
void get_next(char *T,int *next) //获取模式串右滑值next[i]
{
unsigned int i=1,j=0;
next[1]=0;
while(i<strlen(T)-1)
{
if(j==0||T[i]==T[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
int Index_KMP(char *S,char *T,int pos,int *next)
{
int i=pos,j=1,lenS=strlen(S)-1,lenT=strlen(T)-1; //1=<pos<=strlen(S)-1;
while(i<=lenS&&j<=lenT)
{ if(j==0||S[i]==T[j])
{++i;
++j;
}
else j=next[j];
}
if(j>lenT) return (i-lenT);
else return 0;
}
void main()
{
char S[256], T[20];
int next[20],pos,w;
unsigned int i;
cout<<"输入主串(不包括首字符):"<<endl;
scanf("%s",S);
cout<<"输入模式串(不包括首字符):"<<endl;
scanf("%s",T);
cout<<"输入主串匹配起始位置(在1到"<<strlen(S)-1<<")之间:";
cin>>pos;
get_next(T,next);
w=Index_KMP( S, T, pos, next);
if(w==0)cout<<"匹配不成功!"<<'/n';
else cout<<"匹配成功,从主串第"<<w<<"处找到匹配串"<<endl;
}
3.结果:
- 几个算法
- 几个算法
- 几个算法
- 几个算法
- 几个算法
- 几个算法
- 几个算法的问题
- 几个算法题目
- 几个算法题目
- 几个Hash算法
- 几个排序算法源码
- 几个排序算法
- 几个小算法
- 几个C#排序算法
- 几个排序算法
- 几个小算法
- 几个算法题目
- 几个简单排序算法
- equals方法
- 基于.NET Compact Framework的应用程序和库汇总
- 模式匹配
- CGI 安全问题
- WSS3.0 和 MOSS2007 对移动设备浏览器的支持
- 几个算法
- 关于Web2.0创业的讨论
- 上海地块竞购 价格6分钟上涨150% 地价接近房价!
- WSS3.0 和 MOSS2007 对移动设备浏览器的支持(续)
- Observer(观察者)模式
- 华为公司招聘java程序员面试题
- Template模式
- 装饰模式:Decorator
- 什么是T+0