我将获得字符串。我只能从中删除1个元素。如果新的字符串变成回文,我将其删除后,我必须打印"是"否则"否"。
例如,我收到一个字符串" abdbca"。在这里,我可以删除第5个索引' c'并使它成为回文,我必须打印"是"。另一方面,如果字符串类似于" abcd"我只能通过删除一个字符来使它成为回文。因此,我必须打印#34;否"。
我尝试过,但我的代码效率不高。任何人都可以建议我一个有效的方法吗?我必须在不到2.5秒的时间内检查10 ^ 5长度的字符串。
我尝试这样做的方式如下所示:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define REP(i,n) for(int i=0;i<n;i++)
#define MAX 100010
using namespace std;
bool isPalindrome(char abc[]){
int len = strlen(abc), lem = len/2;
for(int i=0,n=len-1;i<=lem;i++,n--) if(abc[i]!=abc[n]) return false;
return true;
}
int main()
{
int tc;
char str[MAX];
scanf("%d",&tc);
while(tc--){
scanf("%s", str);
int length = strlen(str), len = length - 1, z = length % 2, res = 0, ans = 0, b=0,lem = length / 2;
for(int i = 0;i<length;i++){
int n=0, m=1;
for(int x = 0, y = len;x<i && y!=i;x++,y--){
n++;
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(i>lem) for(int x=n,y=len-n-1;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
else for(int x=n+1,y=len-n;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(m==1) {printf("YES\n");b++;break;}
}
//if(length <= res) printf("NO\n");
if(b==0) printf("NO\n");
}
return 0;
}
答案 0 :(得分:2)
由于您只需删除一个字符,您可以通过修改回文检查以线性时间进行删除。这个想法是你从头到尾比较字符到结尾的字符,并在第一个不匹配时停止。如果从不匹配对中删除一个字符并获得回文,则返回true,否则返回false。我在下面的C ++中实现了这个想法。
#include<iostream>
#include<string>
using namespace std;
bool palindromeExists(string s)
{
int i = 0;
int j = s.length()-1;
while(i < j)
{
if(s[i] != s[j]) //first mismatch
break;
i++;
j--;
}
int tempj = j-1; //remove s[j]
int tempi = i;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
break;
tempi++;
tempj--;
}
if(tempi >= tempj) //palindrome found?
return true;
tempi = i+1; //remove s[i]
tempj = j;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
return false;
tempi++;
tempj--;
}
return true;
}
int main()
{
string s = "abca";
if(palindromeExists(s))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
如果字符串已经是回文,或者在删除一个字符后它可以是回文,则应该返回true。我希望我不会错过任何角落案件。
答案 1 :(得分:2)
您可以在此处参考c ++中的完整程序。输入字符串以获取要删除的字符的索引。字符串反转在palim()函数中执行。如果字符串已经是回文,则返回-1。
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
bool palim(string s)
{
string s2;
s2=string(s.rbegin(),s.rend());
if(s2==s)
{
return true;
}
else
{
return false;
}
}
int check(string s)
{
int x;
if(s.length()%2==0)
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>=s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
else
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
return x;
}
int main()
{
string s;
cin>>s;
if(palim(s))
{
cout<<"-1"<<endl;
}
else
{
cout<<check(s)<<endl;
}
return 0;
}
答案 2 :(得分:1)
与turingcomplete类似,但有子功能:
bool isPalindrome(std::string::const_iterator& start, std::string::const_iterator& end)
{
while (start < end) {
--end;
if (*start != *end) {
return false;
}
++start;
}
return true;
}
bool test(const std::string& s)
{
auto start = s.begin();
auto end = s.end();
if (isPalindrome(start, end)) {
// If we remove the middle character of a palindrome,
// We still have a palindrome.
return true;
}
// Now test if there is a palindrome
// if we skip the mismatch char from the start or from the end.
auto start2 = start;
auto end2 = end;
++start2;
--end;
return isPalindrome(start, end) || isPalindrome(start2, end2);
}