关于洛古p1019单次接龙的一点看法

来源:互联网 发布:淘宝客服转正评估表 编辑:程序博客网 时间:2024/06/08 13:52
/*注:原题解转载的其他人的,只是加了一些个人想法 1.lin为存单词的数组,t为输入单词的个数,vis数组存的是使用的次数,、len数组表示没一个单词的长度 。2.此题目的状态是单词的位置和长度(i,length)*/ #include<iostream>  #include<cstring>  #include<cmath>  using namespace std;  struct node{      char lin[1000];  }s[20];  // 结构体 s 用于储存单词 /*此步解决了保存单词的问题,使可以一个一个字母的保存,反思也可以在输入一些单词,按单词长度从大到小输出 */  int t,ans;  int vis[20];  //标记数组,每一次搜索初始化为 0,单词使用一次加一,超过二就不能继续使用 ,即小于等于2.  int len[20];  //单词长度数组,表示每一个单词的长度   /*found函数stp选择的上一个单词下标,i为后一个,例子在后面首先 进行for循环,循环的意义也就是从之前的单词最后一个开始和后面的单词从前向后比较。所以总结一下循环的意义1.在dp中确定长度l和范围2.在字符串搜索中是两个单词比较,可参照kmp算法。 如果(if)在for循环中的q与后面单词的第一个字母相等,那就好办了,直接往后搜索。  做判断用的。  然后定义一个相同位数,后面dfs说过。从q开始向前一个单词最后一个字母前进,  后面的单词从第一个字母向后面前进,一一比较。  比较不过的内层for循环就break。注意!一定要比到上一个字符的最后一个字符答案才有效   因为要从 最后一个字母接嘛。然后返回x。 */int found(int stp,int i){ //stp代表上一个已经选择的单词下标 i表示当前的单词下标       int q,w,j;      for(q=len[stp]-1;q>=1;q--){   //为使长度最长,从上一个单词的末尾开始搜索           if(s[stp].lin[q]==s[i].lin[0]){  //第一个字符匹配后继续看后面还有多少位               int x=0;         //相同位数               for(w=q,j=0;w<len[stp]&&j<len[i];w++,j++){                  if(s[stp].lin[w]==s[i].lin[j])x++;                  else break;              }              if(w==len[stp])return x;//注意!一定要比到上一个字符的最后一个字符答案才有效           }      }      return 0;  }  /*dfs函数dfs函数的状态就是(i,length),也就是已知量,目的是求输出以此字母开头的最长的“龙”的长度。 stp指的是上一个已经选择的单词,也就是“i” */void dfs(int stp,int length){ //上一个已经选择的单词  当前的最长单词长度       int i;      bool mark=false;//以旗子来判断,是否找到      for(i=0;i<t;i++){          if(vis[i]>2)continue;//单词已经被找过两次以上,跳过           int x=found(stp,i);  //x代表上一个单词与当前单词的匹配位数           if(x!=0){   //匹配位数不为0就继续进行下一次的单词搜索               mark=true;              length+=(len[i]-x);  //当前长度增加//举个例子,比如length和theacter,这两个单词有th这两个字母//重合的,所以结合就是lengtheacter,所以length+=(len[i]-x);               vis[i]+=1;    //当前单词用过一个加一               dfs(i,length);//然后i就变成了“上一个”继续去找了。              //上一步递归不符合题意返回至此,长度减去不符合题意的单词,单词的使用次数减一,继续选择单词               length-=(len[i]-x);  //回溯法原理。             vis[i]-=1;          }      }      if(mark==false){     //如果已经找不到单词,比较之前已经得到过的答案选择最长的单词数           ans=max(ans,length);      }  }  int main(){      int i;      char l1;      cin>>t;      for(i=0;i<t;i++){          cin>>s[i].lin;          len[i]=strlen(s[i].lin);      }      cin>>l1;      ans=0;      memset(vis,0,sizeof(vis));  //初始化单词标记数组      for(i=0;i<t;i++)if(s[i].lin[0]==l1){          vis[i]++; //每个单词使用一次,一个一个来。           dfs(i,len[i]);//当前使用的单词下标与长度       }      cout<<ans;//输出结果       return 0;  }

看法都在注释里面
原创粉丝点击