Алгоритъм за най-дълъг квадратен подниз

Търся алгоритъм (в Java), който ще позволи на потребителя да въведе низ и програмата ще върне най-дългия квадратен подниз. Например, ако потребителят въведе „poofoofoopoo“, тогава програмата връща „Longest Square Substring: foofoo“. Ако някой може да напише такъв алгоритъм, ще бъда много благодарен!

Първата ми мисъл беше да модифицирам алгоритъма на Manacher, който връща най-дългия палиндромичен подниз (в линейно време).

Ето кода на Java, който имам за алгоритъма на Manacher:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class LongestPalindrome 
{
	// function to pre-process string 
	public String preProcess(String str) 
	{
		int len = str.length();
		if (len == 0)
		{
			return "^$";
		}
		String s = "^";
		for (int i = 0; i < len; i++)
		{
			s += "#" + str.charAt(i);    
		}
		s += "#$";
		return s;
	}
	
	// function to get largest palindrome sub-string 
	public String getLongestPalindrome(String str)
	{
		// pre-process string 
		char[] s = preProcess(str).toCharArray();
		int N = s.length;
		int[] p = new int[N + 1];
		int id = 0; 
		int mx = 0;
		for (int i = 1; i < N - 1; i++) 
		{
			p[i] = 0;
			while (s[i + 1 + p[i]] == s[i - 1 - p[i]])
			{
				p[i]++;
			}
			if (i + p[i] > mx) 
			{
				mx = i + p[i];
				id = i;
			}
		}
		// length of largest palindrome 
		int maxLen = 0;
		// position of center of largest palindrome 
		int centerIndex = 0;
		for (int i = 1; i < N - 1; i++) 
		{
			if (p[i] > maxLen) 
			{
				maxLen = p[i];
				centerIndex = i;
			}
		}
		// starting index of palindrome 
		int pos = (centerIndex - 1 - maxLen)/2;
		return str.substring(pos , pos + maxLen);        
	}
	
	// Main Function
	public static void main(String[] args) throws IOException
	{    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("LongestPalindrome Algorithm Test\n");
		System.out.println("\nEnter String");
		String text = br.readLine();
		
		LongestPalindrome m = new LongestPalindrome(); 
		String LongestPalindrome = m.getLongestPalindrome(text); 
		System.out.println("\nLongest Palindrome: "+ LongestPalindrome);    
	}    
}


person tig2042    schedule 06.03.2015    source източник


Отговори (1)


Съседните поднизове и палиндромите са доста различни според мен.

Един метод за намиране на най-дългия съседен подниз е да се запази масив от индекси. В началото това е просто изброяване от 0 до (но не включително) str.length. Сортирайте този масив, така че

str.substr(a) < str.substr(b) 

което във вашия пример дава:

[3]     foofoopoo
[6]     foopoo
[2]     ofoofoopoo
[5]     ofoopoo
[1]     oofoofoopoo
[4]     oofoopoo
[7]     oopoo
[8]     opoo
[9]     poo
[0]     poofoofoopoo
[11]    o
[10]    oo

След това преминете през масива и потърсете съседни записи a и b където

str.substr(a, a + d) == str.substr(b, b + d)

с

d = abs(a - b)

След това низът

str.substr(min(a, b), min(a, b) + 2 * d)

е кандидат. Уверете се, че не излизате извън края на низа, когато създавате поднизове.

person M Oehm    schedule 06.03.2015