字元(不是字串)包含問題

來源:互聯網
上載者:User


問題描述:

假設這有一個各種字母組成的字串,假設這還有另外一個字串,而且這個字串裡的字母數相對少一些。從演算法是講,什麼方法能最快的查出所有小字串裡的字母在大字串裡都有? 比如,如果是下面兩個字串: String 1: ABCDEFGHLMNOPQRS String 2: DCGSRQPOM 答案是 true,所有在 string2 裡的字母 string1 也都有。    如果是下面兩個字串:
  String 1: ABCDEFGHLMNOPQRS    String 2: DCGSRQPOZ   

答案是 false,因為第二個字串裡的 Z 字母不在第一個字串裡。 

相關問題:字串中第一個值出現一次的字元。

方法1:hash

             把字串1中的每個字元都映射到數組中,數組的下標是char強制類型轉換為int之後的

             值大小,給定下標的數組元素的值為該字元在字串中出現的次數。再拿字串2中的字元一一

             對比即可。時間複雜度是O(m+n),空間複雜度是O(1) (固定是256);

             很像計數排序,因為此時hash的演算法是   hash(c)=(int)c。

代碼如下:

public class ContainChar {public char[] c1;public char[] c2;public int[] h = new int[256];public ContainChar(String s1,String s2){this.c1 = s1.toCharArray();this.c2 = s2.toCharArray();}public int hash(char c){return (int)c;}public boolean isContain(){for(int i = 0; i < c1.length; i++){h[hash(c1[i])]++;}for(int i = 0; i < c2.length ;i++){if(hash(c2[i]) == 0){return false;}}return true;}public static void main(String[] args){String s1 = "abcdefghijk";String s2 = "dhk";ContainChar c = new ContainChar(s1, s2);System.out.println(c.isContain());}}

輸出為ture。

如果問題是第一個只出現一次的字元,將字串映射之後,在一次遍曆字串,找到只出現一次的字元返回即可。

類似的,找到只出現2次,3此等等都可以照這個思路。

字串是最適合用計數排序的,因為字元的最大值很小(256,雖然char是2byte,但是ascii碼都位於前256)。


方法2:BitMap

             BitMap常常用於輸入規模很大,給你40億個輸入,再給你一條記錄問你是否在輸入中,這時候用BitMap或者布隆過濾器

             都是適合的。原理:一個byte 0 是   00000000 ,輸入一個4  ,變為 00001000。再輸入一個7,變為 00001001。意思是

             用一個byte就能表示0~7的數。簡單例子:

            

public class BitMap {public byte[] b;//輸入數組和數組最大值public BitMap(int[] a,int max){b = new byte[(max % 8) +1];for(int i = 0;i < a.length; i++){add(a[i]);}}//把給定的value放到Bitmap中public void add(int value){int k = value / 8; //找到該value的在數組中位置int mod = value % 8; //找到應該將那一位置1byte num = 1;b[k] = (byte) (b[k] | (num<<(7-mod)));}public boolean isContain(int value){//判斷給定數是否在bitmap中int k = value / 8; //找到該value的在數組中位置int mod = value % 8; //找到應該將那一位置1byte num = 1;if((b[k] & (num<<(7-mod))) == 0){return false;}elsereturn true;}public static void main(String[] args){//用2byte的大小表示了10個int(40byte)int[] a = {1,2,3,4,5,6,7,8,9,10};BitMap b = new BitMap(a, 10);System.out.println(b.isContain(8) + " " + b.isContain(11));}}

輸出為 true false

類似的,把第一個字串載入到bitmap中之後,再依次對比即可。

(似乎這個用bitmap有點複雜。。。不過還是能解決問題)

對於第一個只出現一次的字元,就更加複雜了,我們用2位來表示一個數,00 00 00 01 代表4出現了1次,00 00 00 10 代表4出現了至少2次……。 


方法3:找到256個素數,和字元一一對應。將字串1乘起來。依次看字串1的積能不能將所有字串2的字元對應的素數整除。

             很神奇的做法!


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.