题目如下:
算法分析
1.根据题意,讨论bfs还是dfs的选择。
dfs:
DFS沿着树的深度遍历树的节点,
选一条路一直走到底,回溯,遍历所有的子节点,进而达到全局搜索的目的
栈(先进后出)
和BFS相似,只是稍微做了一丝改变
1、创建一个空栈stack(用来存放节点)和一个空列表visit(用来存放已访问的节点)
2、依次将起始点及邻接点加入stack和visit中
3、poo出栈中最后进入的节点,从图中获取该节点的邻接点
4、如果邻接点不在visit中,则将该邻接点加入stack和visit中
5、输出pop出的节点
6、重复3、4、5,直至栈为空
bfs:
BFS类似于树的层次遍历过程,从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。
舍去空间换时间。
队列(先进先出)
1、创建一个空队列queue(用来存放节点)和一个空列表visit(用来存放已访问的节点)
2、依次将起始点及邻接点加入queue和visit中
3、poo出队列中最先进入的节点,从图中获取该节点的邻接点
4、如果邻接点不在visit中,则将该邻接点加入queue和visit中
5、输出pop出的节点
6、重复3、4、5,直至队列为空
原文链接:https://blog.csdn.net/weixin_45705162/article/details/108296417
根据题目,dfs适用于找所有情况,而bfs适用于找最短路径,因此为了找到最长长度选择dfs.
分析题目:
一、tip:
1.每个字符串最多用2次
2.为求最大长度,应尽量使字符串有最小的重合长度
3.重合度%100的两字符串不行,重合度为0也不行
二、函数分析
1.int match(int x,int y)
at | touch | cheat | choose | tact | |
at | 0 | 1 | 0 | 0 | 1 |
touch | 0 | 0 | 2 | 2 | 0 |
cheat | 0 | 1 | 0 | 0 | 1 |
choose | 0 | 0 | 0 | 0 | 0 |
tact | 0 | 1 | 0 | 0 | 0 |
根据图可得,利用一个lg[][]二维数组储存两字符串之间的重合部分
算法流程:
1.采用一个bool型变量判断字符串是否会相同
2.这里比较巧妙,采用了双层嵌套模式,首先第一层嵌套是从首字符串的末尾开始,
从一开始截取字符串,直到截取完整个字符串,第二层嵌套则是从被截取的字符串开始,进行首字符串与第二个字符串之间的比较;
3。这里涉及到了两个判断,第一个判断是假如在每部分截取中出现了不一样,则pp为假,无法返回,必须重新截取,直到找到完全一样的截取部分,而该部分也由于字符串的由小到大遍历而变成了最小字符相同长度。
4.需要注意的是,返回的是str[x].size()-k,k表示从字符串首字母开始计数,之后的长度,用str[x].size()减去就是重合长度
int match(int x,int y)
{
int k;
bool pp = true;
int ky = 0;
for(int k = str[x].size()-1;k>=0;k--)
{
for(int kx = k;kx < str[x].size();kx++)
{
if(str[x][kx]!=str[y][ky++])
{
pp = false;
break;
}
}
if(pp==true)
{
return str[x].size()-k;
}
pp = true;
ky = 0;
}
return 0;
}
2.dfs
void dfs(int p) //p表示传送进来的第几个字符串
dfs标准格式:先判断在利用循环回溯
tip:这里有个地方我也不清楚,awa
关于这里的bool类型 jx的使用,按理来说,每次向下搜索的时候,将ans与an进行比较,每次都找到最大的ans,可是洛谷会出手。
代码流程:
1.对次字符串进行循环遍历,当字符串使用超过2次,重合率为0,重合率为100时,跳过该循环,从下个字符串开始
2.利用字符串长度减去重合长度,得到an,vis[i]++标明使用过一次,jx = true(不知道为什么),利用dfs进行深搜,an与vis进行回溯
3.当jx==false时,求max
void dfs(int p)
{
bool jx = false;
for(int i = 0;i<n;i++)
{
if(vis[i]>=2) continue;
if(lg[p][i]==0) continue;
if(str[p].size()==lg[p][i]||str[i].size()==lg[p][i])
{
continue;
}
an += str[i].size() - lg[p][i];
vis[i]++;
jx = true;
dfs(i);
an -= str[i].size() - lg[p][i];
vis[i]--;
}
if(jx==false)
{
ans = max(ans,an);
}
return;
}
3.int main()
1.输入输出
2.调用函数,找到二维数组lg[][]的的值
3.将输入的ch单拎出来,处理完之后,进行深搜,深搜别忘了回溯!
代码如下:
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
int n;
#define MAXUSED 2
#define MAXSIZE 22
int vis[MAXSIZE];
int lg[MAXSIZE][MAXSIZE];
string str[MAXSIZE];
int an = -1;
int ans = 0;
int match(int x,int y)
{
int k;
bool pp = true;
int ky = 0;
for(int k = str[x].size()-1;k>=0;k--)
{
for(int kx = k;kx < str[x].size();kx++)
{
if(str[x][kx]!=str[y][ky++])
{
pp = false;
break;
}
}
if(pp==true)
{
return str[x].size()-k;
}
pp = true;
ky = 0;
}
return 0;
}
void dfs(int p)
{
bool jx = false;
for(int i = 0;i<n;i++)
{
if(vis[i]>=2) continue;
if(lg[p][i]==0) continue;
if(str[p].size()==lg[p][i]||str[i].size()==lg[p][i])
{
continue;
}
an += str[i].size() - lg[p][i];
vis[i]++;
jx = true;
dfs(i);
an -= str[i].size() - lg[p][i];
vis[i]--;
}
if(jx==false)
{
ans = max(ans,an);
}
return;
}
int main()
{
cin>>n;
for(int i = 0;i < n;i++)
{
cin>>str[i];
}
char ch;
cin>>ch;
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
lg[i][j] = match(i,j);
}
}
for(int i = 0;i < n;i++)
{
if(str[i][0]==ch)
{
vis[i]++; //表示用过一次
an = str[i].size();
dfs(i);
vis[i] = 0;
}
}
cout<<ans<<endl;
return 0;
}