B - ZJM 与生日礼物(选做)
ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了。只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM。Q老师 给了 ZJM 一些仅有 01 组成的二进制编码串, 他问 ZJM:是否存在一个串是另一个串的前缀.
Input
多组数据。每组数据中包含多个仅有01组成的字符串,以一个9作为该组数据结束的标志。
Output
对于第 k 组数据(从1开始标号),如果不存在一个字符串使另一个的前缀,输出"Set k is immediately decodable",否则输出"Set k is not immediately decodable"。每组数据的输出单独一行
Sample Input
01
10
0010
0000
9
01
10
010
0000
9
Sample Output
Set 1 is immediately decodable
Set 2 is not immediately decodable
解题思路:
这道题目主要是对于字典树的应用,理解了字典树,那么在逻辑方面没有太多障碍。对于字典树的数组表示,感觉很优秀,数组运用的比较灵活,这在链式前向星中也有同感,有时这些基本变量的运用往往加深自己对基本变量的理解,自我感觉,程序的设计中对于变量的灵活运用,比如变量的具体作用,需要多少变量进行保存,控制,更新等,正是解题思维的一个完整体现。深入理解变量对于清晰简单化我们的思路有很大作用。
代码:
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;
struct func{
int tot,root;
int local[100000][2];
int flag[100000];
void init()
{
tot=0;
root=0;
memset(local,-1,sizeof(local));
memset(flag,0,sizeof(flag));
}
bool insert(string s)
{
int now=0;
for(int i=0;i<s.size();i++)
{
int cc=s[i]-'0';
if(local[now][cc]==-1)
{
if(flag[now]==1)
return true;
local[now][cc]=++tot;
flag[now]=0;
}
else if(i==s.size()-1)
return true;
now=local[now][cc];
}
flag[now]=1;
return false;
}
};
string s;
int label=1;
int main()
{
func ff;
ff.init();
int a=0;
while(cin>>s)
{
if(s[0]!='9')
a=a|ff.insert(s);
else
{
if(a==1)
cout<<"Set "<<label<<" is not immediately decodable"<<endl;
else
cout<<"Set "<<label<<" is immediately decodable"<<endl;
label++;
ff.init();
a=0;
}
}
}在这里插入代码片
C - ZJM 与纸条(选做)
ZJM 的女朋友是一个书法家,喜欢写一些好看的英文书法。有一天 ZJM 拿到了她写的纸条,纸条上的字暗示了 ZJM 的女朋友 想给 ZJM 送生日礼物。ZJM 想知道自己收到的礼物是不是就是她送的,于是想看看自己收到的礼物在纸条中出现了多少次。
Input
第一行输入一个整数代表数据的组数,每组数据第一行一个字符串 P 代表 ZJM 想要的礼物, 包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 并且字符串长度满足 1 ≤ |P| ≤ 10,000 (|P| 代表字符串 P 的长度).
接下来一行一个字符串 S 代表 ZJM 女朋友的纸条, 也包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 满足 |P| ≤ |S| ≤ 1,000,000.
Output
输出一行一个整数代表 P 在 S中出现的次数.
Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
Sample Output
1
3
0
解题思路:
这是一道利用KMP算法进行求解的问题,目的就在于简单利用KMP算法进行问题的求解。算法的核心在于next数组的运用,对于字符串匹配的问题,我们或许有些杂乱的其他想法,但是对于KMP算法,给我的感觉便是思路比较规整,逻辑比较清晰,是一种十分静态的算法。(这是相对于动态规划来讲的)脑子比较容易想清楚。代码逻辑于实现基本都是固定的,详细看代码。
代码:
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
int T;
string a,b;
int ans=0;
int next[10005];
int func(string a,string b)
{
ans=0;
memset(next,0,sizeof(next));
for(int i=1,j=0;i<a.size();i++)
{
while(a[i]!=a[j]&&j)
{
j=next[j-1];
}
if(a[i]==a[j])
j++;
next[i]=j;
}
int label=0;
for(int i=0;i<b.size();i++)
{
while(label&&b[i]!=a[label])
{
label=next[label-1];
}
if(b[i]==a[label])
{
label++;
}
if(label==a.size())
{
ans++;
label=next[label-1];
}
}
return ans;
}
int main()
{
cin>>T;
while(T--)
{
cin>>a>>b;
cout<<func(a,b)<<endl;
}
}在这里插入代码片