1. 程式人生 > >求字串中的,最長不重複子串--java程式碼

求字串中的,最長不重複子串--java程式碼

package ali;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
	public static void main(String[] args) {  
        String str1 = "hellowdhelloko";  
        max_unique_substring3(str1);  
        
    }  
	
	//O(N^2)的時間複雜度  
	static void max_unique(String str)   
	{  
		// begin用來儲存 最長不重複子串的 開始索引
	    int begin=0;  
	    // maxlen用來儲存最長不重複子串的 長度
	    int maxlen = 0;  
	    // 定義一個容器,用來儲存遍歷時候遇到的每一個字元的出現次數情況
	    TreeMap<Character,Integer>  tm = new TreeMap<Character,Integer>(); 
	    int n = str.length();  
	    
	    int j=0;
	    for(int i=0; i<n; ++i)  
	    {  
	        // 初始化   hash 這個陣列,用0補充
	    	for(int k=0; k<n; k++)
	    	{
	    		tm.put(str.charAt(k), 0); 
	    	}
	    	tm.put(str.charAt(i), 1); 
	    	// 往i+1開始往後找,遇到和i索引處不一樣的元素,就將那個位置的“鍵值”置1;
	    	// 遇到一樣的就 break,讓j停在現在這個位置
	        for(j=i+1; j<n; ++j)  
	        {  
	            if(tm.get(str.charAt(j)) == 0)  
	            	tm.put(str.charAt(j), 1); 
	            else  
	                break;  
	        }  
	        // 上面j剛好停在了,第一次出現重複的那個位置,相減即為這個時候的最長子串長度,
	        // i索引是其的開始
	        if(j-i > maxlen)  
	        {  
	            maxlen = j-i;  
	            begin = i;  
	        }  
	    }  
	    System.out.println(maxlen + " " + str.substring(begin, begin+maxlen)) ;
	      
	}  
	
	//O(N)的時間複雜度  
	static void max_unique_substring3(String str)   
	{  
	    int maxlen = 0;  
	    int begin = 0;  
	    int n = str.length();  
	    int[] next = new int[n]; //next[i]記錄了下一個與str[i]重複的字元的位置  
	    int[] first = new int[n+1]; //first[i]記錄str[i]後面最近的一個重複點  

	    TreeMap<Character,Integer>  tm = new TreeMap<Character,Integer>(); 
	    // 初始化   tm 這個陣列,用0補充
    	for(int k=0; k<n; k++)
    	{
    		tm.put(str.charAt(k), n); 
    	}
	    
	    first[n] = n;  
	    for(int i=n-1; i>=0; i--)  
	    {  
	    	// next[i]記錄了下一個與str[i]重複的字元的位置    first[i]記錄str[i]後面最近的一個重複點
	        
	    	// tm中存放的就是  下一個與str[i]重複的字元的位置 ,
	    	next[i] = tm.get(str.charAt(i));  
	    	// 在這會進行 更新 tm
	        tm.put(str.charAt(i),i);
	        // 如果next存放的這個 索引 小於 str[i]後面最近的 1 個重複點。如果無,就是 n 這個數字
	        if (next[i] < first[i+1])  
	            first[i] = next[i];  
	        else  
	            first[i] = first[i+1]; //生成first[]表,複雜度是O(N)的  
	    }  
	    for(int i=0; i<n; i++)  
	    {  
	        if (first[i]-i > maxlen)  
	        {  
	            maxlen = first[i]-i;  
	            begin = i;  
	        }  
	    }  
	    System.out.println(maxlen + " " + str.substring(begin, begin+maxlen));
	    
	}  
	
}