압축 부호화 [820 개 단어 (단어 짧은 인코딩)

단어리스트로부터,이리스트는 문자열 S 인덱스와 인덱스리스트 A.로 인코딩 될
예를 들어,리스트가있는 경우 [ "시간", "나" , "종", 우리는 S = "# 시간 벨 #"과 인덱스 = 0, 2, 5와 같이 표현 될 수있다 ].
각 인덱스를 들어, 우리는 단어의 이전 목록을 복원하려면 "#"이 끝날 때까지 위치에있는 문자열 S에서 문자열 인덱스를 읽어 시작할 수 있습니다.
그런 다음 인코딩 주어진 단어 목록의 성공에 문자열의 최소 길이는 얼마입니까?

예 1 :

입력 : 단어 = "시간", "나", "종"]
출력 : 10
설명 : S = "# 시간 벨 # ", 인덱스 = 0, 2, 5].

개인의 생각은 : 첫째, 만 두 단어 가정 문제를 이해하기에, B는 그 때 A, B 또는 A 접미사의 접미사 B는 문제가 너무 분명 여부를 확인해야 할 것이다, 우리가 서로를 때마다 결정하는 A 또는 B 여부 우리는 단어의 끝을 정렬 판사을 보장 할 수 있도록 자사의 접미사,가, 생각할 수있는 일종의 분명히 불편, 그것은 첫 번째 단어 반전, 다음 분류 간주 될 수 있습니다.

예를 들어, 우선, 워드 그룹

string[] words = { "outint", "like", "int", "dislike", "nt" };

역으로 첫 번째 단어를
그림 삽입 설명 여기
다음과 정렬 단어 그룹 - 긍정적 순서
그림 삽입 설명 여기
단어는 종류를 설정 - 역순으로
그림 삽입 설명 여기
정렬 한 후, 같은 값 (접두사) 훨씬 더 편리, 한 라인에 패리티 인접한 값, 여기서주의에 관해서는 긍정적 인 순서 정렬을 사용하는 경우이다 찾고 전면 후면에서 통과하기 위해 필요한 비교 ([4]=>[3]=>...=>[0])역에 뒤로, 앞 ([0]=>[1]=>...=>[4])이유도 위의 그림 참조 이해를 위해.

씨#

class Program
{
    static void Main(string[] args)
    {
        string[] words = { "outint", "like", "int", "dislike", "nt" };
        Console.WriteLine(MinimumLengthEncoding(words));
        Console.Read();
    }

    public static int MinimumLengthEncoding(string[] words)
    {
        /*首先要理解题意,假设只有两个词A,B 
         * 那么就要检查A是否是B的后缀,或者B是A的后缀,
         * 这样显然麻烦,我们每次都要互相判断A或B是否是其的后缀,
         * 可以想到排序,这样就能保证判断一次,
         * 以单词的末尾进行排序显然是不方便的,所以可以考虑先将单词反转,然后进行排序
         */

        //1.使用HashSet<>和SortedSet<>容器时间会明显变长,因为每次加入新元素都要排序去重,
        //所以这里使用List<>
        List<string> wordList = new List<string>();

        //2-1.遍历所有单词,将其反转
        foreach (string word in words)
        {
            //添加到List中
            wordList.Add(new string(word.Reverse().ToArray()));
        }

        //2-2去重,倒序
        //倒序,保证相同前缀的单词长的在前面
        wordList = wordList.Distinct().OrderByDescending(reWord => reWord).ToList();

        //3.首位作为初始值
        string curStr = wordList.First();       //初始索引字符串
        int count = curStr.Length;    //初始索引字符串长度

        //4.遍历单词集
        for (int i = 0; i < wordList.Count - 1; i++)
        {
            //加上每次比较后的结果,ref保证当前索引字符串更新
            count += CompareWords(ref curStr, wordList.ElementAt(i + 1));
        }

        //5.加上最后一个#
        return ++count;
    }

    /// <summary>
    /// 比较是否是前缀
    /// </summary>
    /// <param name="curStr">当前索引字符串</param>
    /// <param name="nextWord">下一个准备比较单词</param>
    /// <returns></returns>
    private static int CompareWords(ref string curStr, string nextWord)
    {
        int cnt = 0;

        //4-1.找出两个词中较短的数值
        int min = Math.Min(curStr.Length, nextWord.Length);
        
        //4-2.从后向前检查,
        //因为判断是否前缀,所以最后不同就不是前缀了,前面的就不用判断了
        for (int i = min - 1; i >= 0; i--)  
        {
            //i==0即直到最后一个也符合,即next是cur的前缀
            if (curStr[i] == nextWord[i] && i == 0)
            {
                cnt = 0;
            }
            //不同,即不是前缀,直接跳出
            else if (curStr[i] != nextWord[i]) 
            {
                curStr = nextWord + curStr;
                cnt = nextWord.Length + 1;//有一个#
                break;
            }
        }

        //4-3.最后返回本次计算后需要的长度
        return cnt;
    }
}

요구의 다른 세트를 시간
그림 삽입 설명 여기

게시 62 개 원래 기사 · 원의 찬양 (68) · 전망 160 000 +

추천

출처blog.csdn.net/ZUFE_ZXh/article/details/105182566