Return the number of distinct non-empty substrings of text&nbsp;that can be written as the concatenation of some string with itself (i.e. it can be written as a + a&nbsp;where a is some string).

&nbsp;
Example 1:

Input: text = "abcabcabc"
Output: 3
Explanation: The 3 substrings are "abcabc", "bcabca" and "cabcab".


Example 2:

Input: text = "leetcodeleetcode"
Output: 2
Explanation: The 2 substrings are "ee" and "leetcodeleetcode".


&nbsp;
Constraints:


	1 &lt;= text.length &lt;= 2000
	text&nbsp;has only lowercase English letters.


class Solution:
    def distinctEchoSubstrings(self, s: str) -> int:
        hash=set()
        n=len(s)
        for i in range(n):
            for j in range(i):
                
                if (i-j)&1==1:
                    
                    k=(i-j)//2
                    
                    if s[j:j+k+1]==s[j+k+1:i+1]:
                        hash.add(s[j:j+k+1]+s[j+k+1:i+1])
        return len(hash)
                    
                    
                    
        
class Solution {
    private static final int PRIME = 101;
    private static final int MOD = 1_000_000_007;
    public int distinctEchoSubstrings(String text) {
        int n = text.length();
        
        // dp[i][j] : hash value of text[i:j]
        int[][] dp = new int[n][n];
        for (int i = 0; i < n; i++) {
            long hash = 0;
            for (int j = i; j < n; j++) {
                hash = hash * PRIME + (text.charAt(j) - 'a' + 1);
                hash %= MOD;
                dp[i][j] = (int) hash;
            }
        }
        
        Set<Integer> set = new HashSet<>();
        int res = 0;
        for (int i = 0; i < n-1; i++) {
            // compare text[i:j] with text[j+1: 2j-i+1]
            for (int j = i; 2*j - i + 1 < n; j++) {
                if (dp[i][j] == dp[j+1][2*j - i+1] && set.add(dp[i][j])) res++;
            }
        }
        
        return res;
    }
}
class Solution {
public:
    static const int N=2005;
    int mod=1e9+7;
    int B=31;
    long long h[N],p[N],invp[N];
    int modexp(int x,int y){
        int res=1;
        while(y>0){
            if(y&1) res=((long long)res*x)%mod;
            x=((long long)x*x)%mod;
            y=y>>1;
        }
        return res;
    }
    int sub_hash(int l,int r){
        int ans=h[r];
        if(l>0)
            ans=((ans+mod-h[l-1])*invp[l]*1LL)%mod;
        return ans;
    }
    int distinctEchoSubstrings(string text) {
        set<int> res;
        int ans=0;
        p[0]=1;invp[0]=1;
        for(int i=1;i<2005;i++){
            p[i]=(p[i-1]*B)%mod;
        }
        for(int i=1;i<N;i++){
            invp[i]=(invp[i-1]*modexp(B,mod-2))%mod;
        }
        int n=text.size();
        h[0]=(text[0]-'a'+1);
        for(int i=1;i<n;i++){
            h[i]=(h[i-1]+((text[i]-'a'+1)*p[i])*1LL)%mod;
        }
        for(int len=1;len<=n/2;len++){
            for(int i=0;i<n+1-2*len;i++){
                int a=sub_hash(i,i+len-1);
                int b=sub_hash(i+len,i+2*len-1);
                if(a==b){
                    if(res.find(a)==res.end()){
                        res.insert(a);
                        ans++;
                    }
                }
            }
        }
        return ans;
    }
};
/**
 * @param {string} text
 * @return {number}
 */
var distinctEchoSubstrings = function(text) {
    const store = new Set();
    for (let i = 0; i < text.length; i++) {
        for (let j = i + 1; j < text.length; j++) {
            const left = text.substring(i,j);
			const right = text.substring(j, j + j - i);
            if (left === right) store.add(left);
        }
    }
    return store.size;
};
Distinct Echo Substrings