题目链接:
题意
存在一个长度为n的字符串,现在给出其所有长度(1~n-1)的前缀和后缀,对于每个给出的字符串判断是前缀还是后缀。
题解
由两个长度为n-1的字符串就可以确定整个字符串的内容,设两个字符串分别是t1、t2,if(t1.substr(1,n-1))==t2.substr(0,n-2)),可确定t1是前缀,t2是后缀。当如果原字符串是回文串时,这样的判断还不足以说明,所以注意到一个特点是若t1是前缀,则在所以给出的字符串中至少有n-1个是t1的前缀。
注释
substr()函数定义于头文件<string
(这里还有一个右尖括号加不上是什么鬼5555)
s.substr(pos,n)
pos 从此位置开始拷贝
n 拷贝n长度的字符串
返回一个string,包含s中从pos开始的n个字符的拷贝。
比如string s=“123abc”;
string a=s.substr(2,2);
cout<<a;
结果为3a
1、
若pos为0,则n的默认值为s.size()
若不加参数,则拷贝整个s;
s.substr();运行结果为"123abc";
若只加pos,则会从pos位置开始拷贝剩余全部字符。
s.substr(3); 运行结果为"abc";
2、
若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾。
代码
#include <iostream>
using namespace std;
string s[300];
bool vis[300];
int main()
{
int n;
bool flag=true;
string pre,sur;
string ans;//记录输出结果的字符串
cin>>n;
for(int i=1;i<=2*n-2;i++)
{
cin>>s[i];//输入字符串
if(flag&&(s[i].size()==(n-1)))//捕捉并标记长度为n-1的字符串,发挥一次作用就废了
{
pre=s[i];//先设为前缀,后面检验不行的话咱就换
flag=false;
}
else if(s[i].size()==(n-1))//捕捉另一个长度为n-1的字符串
sur=s[i];//先设为后缀
}
int tot=0;
for(int i=1;i<=2*n-2;i++)
if(s[i][0]==pre[0])tot++;//根据之前设的前缀,计算前缀字符串的数量
if(tot<n-1||pre.substr(1)!=sur.substr(0,n-2))
swap(pre,sur);//检验不过关,前后缀设定错误,交换
vis[300]={0};//也可用memset(vis,0,sizeof vis);
for(int i=1;i<=2*n-2;i++)
{
if(pre.substr(0,s[i].size())==s[i]&&!vis[s[i].size()])
{
vis[s[i].size()]=true;//标记,避免重复检验
ans+="P";
}
else ans+="S";
}
cout<<ans<<endl;
return 0;
}
总结
第一次写博客,记录做题心得,日后一定勤加练习,提高做题能力。