Tutaq ki, — giriş sətri. Alt sətr s_i ... s_j palindromdur, əgər ən azı bir şərt yerinə yetirilirsə:
i \ge j, yəni alt sətr boşdur və ya bir simvoldan ibarətdir;
s_i = s_j və alt sətr s_{i + 1} ... s_{j - 1} palindromdur;
Funksiya IsPal təyin edək, hansı ki, s_i ... s_j alt sətri palindromdursa, , əks halda qaytarır.
Algoritmanın işləmə sürətini artırmaq üçün IsPal(i, j) funksiyasının qiymətlərini iki ölçülü massivin pal[i][j] hüceyrələrində saxlayacağıq.
Sətr superpalindrom adlanır, əgər onu bir və ya bir neçə palindromun konkatenasiyası formasında təqdim etmək olarsa. Məsələn, aşağıdakı sətrlər superpalindromlardır:
Deyək ki,
Burada nəzərdə tutulur ki, i < j, yəni alt sətr uzunluğu ən azı iki.
Baza halları qeyd edək:
Eğer i \ge j, alt sətr ya boş, ya da bir simvoldan ibarətdir. Şərtə görə bu cür sətrlər palindrom sayılmır. Deməli,
Xüsusilə, hər hansı bir mövqe üçün mövqeyi üçün dp[i][i] = 0.
Əgər alt sətr s_i ... s_j palindromdursa və uzunluğu iki və daha çoxdur, o avtomatik olaraq superpalindrom olur (çünki bir palindromdan ibarətdir). Buna görə indekslərin bütün cütləri üçün , burada 0 \le i < j < n, əgər alt sətr s_i ... s_j palindromdursa, dərhal dp[i][j] = 1 qura bilərik.
İndi hesabı ümumi halına baxaq. Alt sətr s_i ... s_j tamamilə palindrom deyil. O halda superpalindrom ola bilər əgər onu iki hissəyə bölmək mümkündür ki, hər biri öz növbəsində superpalindrom olsun.
Bunun üçün bütün mümkün bölünmə mövqelərini nəzərdən keçirəcəyik k~(i < k < j - 1).
Məhdudiyyət k < j - 1 təmin edir ki, hər iki alt sətr
uzunluğu ən azı iki, belə ki, potensial olaraq superpalindrom ola bilər.
Əgər bəzi üçün:
dp[i][k] = 1,
dp[k + 1][j] = 1,
alt sətr s_i ... s_j iki superpalindromların konkatenasiyası olaraq təqdim edilir. Deməli, o özü superpalindromdur və biz dp[i][j] = 1 quraşdırırıq.
Əgər heç bir uyğun üçün bu şərtlər yerinə yetirilmirsə, onda dp[i][j] sıfır olaraq qalır.
Geriyə cütlərinin sayını hesablamaq qalır, harada i < j və dp[i][j] = 1. Bu sətir , alt sətrlər superpalindrom üzərində alt sətrlərin sayıdır.
Misal
Verilmiş misal üçün — sətir "", burada superpalindrom alt sətr mövcuddur:
Sətir "" üçün superpalindrom alt sətr mövcuddur:
Algoritmin həyata keçirilməsi
İşçi massivlər elan edək.
#define MAX 1010
char s[MAX];
int dp[MAX][MAX];
int pal[MAX][MAX];Funksiya IsPal alt sətrin s_i \ldots s_j palindrom olub olmadığını yoxlayır. Alt sətr s_i \ldots s_j palindromdur, əgər s_i = s_j və alt sətr s_{i + 1} \ldots s_{j - 1} də palindromdur.
int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
return pal[i][j] = (s[i] == s[j]) && IsPal(i + 1,j - 1);
}Proqramın əsas hissəsi. Giriş sətirini oxuyuruq. Onun uzunluğunu hesablayırıq.
cin >> s; n = s.size();Massivlər və inicializasiya edirik.
memset(dp,0,sizeof(dp));
memset(pal,-1,sizeof(pal));Bütün alt sətrləri s_i \ldots s_{i + len} sətirdən araşdırırıq uzunluqların artan sırasına görə. Əsas də alt sətrtərin dp[i][j] qiyməti daha qısa alt sətrlərin qiymətlərindən asılıdır.
for (len = 1; len < n; len++)
for (i = 0; i + len < n; i++)
{Alt sətrin sağ sərhəddi s_i \ldots s_{i + len} j = i + len.
j = i + len;Əgər alt sətr s_i \ldots s_j palindromdursa, o, avtomatik olaraq superpalindrom olur.
if (IsPal(i,j))
{
dp[i][j] = 1;
continue;
}Əgər alt sətr s_i \ldots s_j palindrom deyilsə, onu iki superpalindromun konkatenasiyası olaraq təqdim etməyə çalışırıq.
Əgər s_i \ldots s_k və s_{k+1} \ldots s_j superpalindromlardırsa, onda s_i \ldots s_j superpalindromdur.
for(k = i + 1; k < j - 1; k++)
if(dp[i][k] && dp[k + 1][j])
{
dp[i][j] = 1;
break;
}
}Superpalindromların sayını ölçürük. Bu, cüt indekslərin (i, j) sayıdır, hansı ki dp[i][j] = 1.
res = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
res += dp[i][j];Cavabını çıxarırıq.
printf("%d\n",res);Algoritmin həyata keçirilməsi – rekursiya
Giriş sətiri elan edək və işçi massivlər.
#define MAX 1010
string s;
int dp[MAX][MAX], pal[MAX][MAX];Funksiya IsPal alt sətrin s_i \ldots s_j palindrom olub olmadığını yoxlayır. Alt sətr s_i \ldots s_j palindromdır əgər s_i = s_j və alt sətr s_{i + 1} \ldots s_{j - 1} də palindromdır.
int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
return pal[i][j] = (s[i] == s[j]) && IsPal(i+1,j-1);
}Funksiya f s_i \ldots s_j superpalindromdursa, qaytarır.
int f(int i, int j)
{Superpalindrom daha çox simvol ehtiva etməlidir.
if (i == j) return dp[i][j] = 0;Əgər f artıq əvvəllər hesablanıbsa, onun qiymətini qaytarırıq.
if (dp[i][j] != -1) return dp[i][j];Əgər alt sətr s_i \ldots s_j~(i < j) palindromdursa, o həm də superpalindrom olur.
if (IsPal(i,j)) return dp[i][j] = 1;Əgər alt sətr s_i \ldots s_k~(i < k) palindromdursa, alt sətr s_{k+1} \ldots s_j~(k + 1 < j) superpalindromdursa, alt sətr s_i \ldots s_j superpalindromdur.
for (int k = i + 1; k < j - 1; k++)
if (IsPal(i,k) && f(k + 1,j)) return dp[i][j] = 1;Əgər yuxarıda təsvir edilən heç bir şərtlər yerinə yetirilmirsə, alt sətr s_i \ldots s_j superpalindrom deyil.
return dp[i][j] = 0;
}Proqramın əsas hissəsi. Giriş sətirini oxuyurq və onun uzunluğunu hesablayırıq.
cin >> s; n = s.size();Massivlər və inicializasiya edirik.
memset(dp,-1,sizeof(dp));
memset(pal,-1,sizeof(pal));Superpalindromların sayını dəyişənində hesablayırıq.
res = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
res += f(i,j);Cavabını çıxarırıq.
cout << res << endl;Java həyata keçirilməsi
import java.util.*;
public class Main
{
static String s;
static int dp[][], pal[][];
static int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
if (s.charAt(i) == s.charAt(j) && IsPal(i+1,j-1) == 1) pal[i][j] = 1;
else pal[i][j] = 0;
return pal[i][j];
}
static int f(int i, int j)
{
if (i == j) return dp[i][j] = 0;
if (dp[i][j] != -1) return dp[i][j];
if (IsPal(i,j) == 1) return dp[i][j] = 1;
for(int k = i + 1; k < j - 1; k++)
if(IsPal(i,k) == 1 && f(k + 1,j) == 1) return dp[i][j] = 1;
return dp[i][j] = 0;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
s = con.nextLine();
int n = s.length();
dp = new int[n][n];
pal = new int[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
dp[i][j] = -1;
pal[i][j] = -1;
}
int res = 0;
for(int i = 0; i < n; i++)
for(int j = i+1; j < n; j++)
res += f(i,j);
System.out.println(res);
con.close();
}
}