用sunday算法解决字符串匹配问题

来源:互联网 发布:对待新事物的态度知乎 编辑:程序博客网 时间:2024/06/01 09:20
题目内容:
题目说起来很简单,你会读到两个字符串,每个字符串占据一行,每个字符串的长度均小于10000字符,而且第一个字符串的长度小于第二个字符串的。你的程序要找出第一个字符串在第二个字符串中出现的位置,输出这些位置,如果找不到,则输出-1。
注意,第一个字符的位置是0。
注意,第一个字符串在第二个字符串中的位置可能不止一处。
注意,字符串中可能含有空格。
注意,两个字符串的长度一定大于0。
输入格式:
两个字符串,一行一个。
输出格式:
第一个字符串在第二个字符串中出现的位置,按照从小到到的顺序排列,每个数字后面有一个空格。
如果在第二个字符串中找不到第一个字符串,则输出-1。
输入样例:
abba
ababbba abbabbabbabbaacc
输出样例:
8 11 14 17

/////////////sunday算法解决字符串匹配问题///////////////
sunday算法思想:
 对匹配串长度的模式串进行随机顺序的检测,在失败位置生成
 移动数组,根据移动数据最大幅度的减少匹配次数
使用结构体:
 SqString(char data[];int lengthp)//顺序栈保存字符串
函数说明:
 SundayIndex:
 输入:  int start //模式开始匹配位置
   SqString s//模式串
   SqString p//匹配串 
   intScanOrdToUse[]  //对读取顺序进行的顺序读取转译
   intScanOrder[] //随机生成的匹配串读取顺序
   intValueOfShift[] //对错误位置生成的后移数组
 输出:返回匹配成功的字符串起始位置,失败返回-1
算法思路:
 int i=start,j=0; //i代替起始位置,j代表匹配串当前匹配位置
 while 开始位置未到模式串尾,匹配串未结束
  //按检查顺序检查,匹配成功继续下一个
  //失败将模式串定位i移动对应位置
 返回成功与否信息  
/////////////////////////////////////////////////////////////
#include
#include
#include
#define MaxSize 10000
typedef struct
{
 char data[MaxSize];
 int length;
}SqString;
//获取随机排序
void getScanOrder (int len,int ScanOrder[], intScanOrdToUse[])
{
 int i,j;
 srand((unsigned)time(NULL));
 for (i=0; i
 {
  ScanOrder[i] =rand()%len;
  for (j=0; j
  {
   if(ScanOrder[i] == ScanOrder[j])
   {
    i--;break;
   }
  }
 }
 for (i=0; i
  ScanOrdToUse[ScanOrder[i]] =i;
}
//成功匹配位置检查
int checkSucc (int i, SqString p, int ScanOrdToUse[], int k)
 
 while (i>=0)
 {
  if(ScanOrdToUse[i]-k>=0)
  {
   if(p.data[ScanOrdToUse[i]] == p.data[ScanOrdToUse[i]-k])
    i--;//对应位置相同,检查下一位置      
   else//对应位置不相同,成功位置检查失败,返回
    return0;
   
  else
   i--;        
 }
 if (i==-1) //如果成功匹配全部检查成功,返回成功信息
  return1; 
}

//获取ValueOfShift数组
void getValueOfShift (SqString p,int ValueOfShift[],intScanOrder[],int ScanOrdToUse[])

 intj,k;  
 j=0;
 while (j
 {
  k=1;
  while (k < p.length)
    
   if(ScanOrdToUse[j]-k>=0)
   {
    if(p.data[ScanOrdToUse[j]]!=p.data[ScanOrdToUse[j]-k]) 
     if(!checkSucc(j-1,p,ScanOrdToUse,k)) k++;
     elsebreak;    
    else
     k++;  
   }
   else
    if(!checkSucc(j-1,p,ScanOrdToUse,k)) k++;
    elsebreak;      
  }
  ValueOfShift[ScanOrdToUse[j]] =k;  
  j++;
 }   
}
int SundayIndex (int start,SqString s,SqString p,intScanOrdToUse[],int ScanOrder[],int ValueOfShift[])
{
 int i=start,j=0; 
 while (i
 {
  //按检查顺序检查,匹配成功继续下一个
  if(s.data[i+ScanOrdToUse[j]]==p.data[ScanOrdToUse[j]])
   j++;
  else //失败将模式串定位i移动对应位置
  {
   i =i+ValueOfShift[ScanOrdToUse[j]];j=0;
  }
 }
 if (j>=p.length)
  return i;
 else
  return -1;
}
int main ()
{
 char a[MaxSize];
 char b[MaxSize]; 
 SqString s,p;
 int i;
 int loac=0,start=0;
 int existIf = 0;
 intValueOfShift[MaxSize],ScanOrdToUse[MaxSize],ScanOrder[MaxSize];
 
 gets(b);
 gets(a);
 
 for (i = 0; a[i] != '\0'; i++)
  s.data[i] = a[i];
 s.length = i;
 
 for (i = 0; b[i] != '\0'; i++)
  p.data[i] = b[i];
 p.length = i;
 getScanOrder(p.length,ScanOrder,ScanOrdToUse);
 getValueOfShift(p,ValueOfShift,ScanOrder,ScanOrdToUse);
 
 for (;;)
 {
  loac = SundayIndex(start,s,p,ScanOrdToUse,ScanOrder,ValueOfShift);
  if (loac==-1)
   break;
  else 
  {
   printf ("%d",loac);
   existIf =1;
   start =loac+1;
  }
 }
 if (existIf == 0)
  printf("%d",-1);   
}
 
0 0
原创粉丝点击